评论

云开发,实现【最近搜索】和【大家在搜】的存储和读取逻辑

大部分小程序都要用到【搜索】功能,该篇介绍“云开发”模式下如何实现【最近搜索】和【大家在搜】的存储和读取逻辑。

小程序【搜索】功能是很常见的,在开发公司的一个电商小程序的时候想尝试使用“云开发”做系统的后端,而首页顶端就有个搜索框,所以第一步想先解决【搜索】的一些前期工作:【最近搜索】和【大家在搜】关键词的存储和读取逻辑。

效果图如下:

效果视频请点击链接查看:

https://v.vuevideo.net/share/post/-2263996935468719531

或者微信扫码观看:

为什么需要这两个功能?

【最近搜索】:可以帮助用户快速选择历史搜索记录(我这里只保存10个),搜索相同内容时减少打字操作,更加人性化;
【大家在搜】:这部分的数据可以是从所有用户的海量搜索中提取的前n名,也可以是运营者想给用户推荐的商品关键词,前者是真实的“大家在搜”,后者更像是一种推广。

具体实现
流程图:

可以结合效果图看流程图,用户触发操作有三种形式:

  1. 输入关键词,点击搜索按钮;
  2. 点击【大家在搜】列举的关键词;
  3. 点击【最近搜索】的关键词

这里发现1和2是一样的逻辑,而3更简单,所以把1和2归为一类(左边流程图),3单独一类(右边流程图)

两个流程图里都含有相同的片段(图中红色背景块部分):“找出这条记录”->“更新其时间”。故这部分可以封装成函数:updateTimeStamp()。

更新时间指的是更新该条记录的时间戳,每条记录包含以下字段:_id、keyword、openid、timeStamp。其中_id是自动生成的,openid是当前用户唯一标识,意味着关键词记录与人是绑定的,每个用户只能看到自己的搜索记录,timeStamp是触发搜索动作时的时间戳,记录时间是为了排序,即最近搜索的排在最前面。

代码结构:

云函数:

cloudfunctions / searchHistory / index.js

const cloud = require('wx-server-sdk')

cloud.init()

const db = cloud.database()
exports.main = async (event, context) => {
  try {
    switch (event.type) {
      // 根据openid获取记录
      case 'getByOpenid':
        return await db.collection('searchHistory').where({
          openid: event.openid
        }).orderBy('timeStamp', 'desc').limit(10).get()
        break

      // 添加记录
      case 'add':
        return await db.collection('searchHistory').add({
          // data 字段表示需新增的 JSON 数据
          data: {
            openid: event.openid,
            timeStamp: event.timeStamp,
            keyword: event.keyword
          }
        })
        break
      // 根据openid和keyword找出记录,并更新其时间戳
      case 'updateOfOpenidKeyword':
        return await db.collection('searchHistory').where({
          openid: event.openid,
          keyword: event.keyword
        }).update({
          data: {
            timeStamp: event.timeStamp
          }
        })
        break
      // 根据openid和keyword能否找出这条记录(count是否大于0)
      case 'canFindIt':
        return await db.collection('searchHistory').where({
          openid: event.openid,
          keyword: event.keyword
        }).count()
        break
      // 根据openid查询当前记录条数
      case 'countOfOpenid':
        return await db.collection('searchHistory').where({
          openid: event.openid
        }).count()
        break
      // 找出该openid下最早的一条记录
      case 'getEarliestOfOpenid':
        return await db.collection('searchHistory').where({
          openid: event.openid
        }).orderBy('timeStamp', 'asc').limit(1).get()
        break
      // 根据最早记录的id,删除这条记录
      case 'removeOfId':
        return await db.collection('searchHistory').where({
          _id: event._id
        }).remove()
        break

      // 删除该openid下的所有记录
      case 'removeAllOfOpenid':
        return await db.collection('searchHistory').where({
          openid: event.openid
        }).remove()
        break
    }
  } catch (e) {
    console.error('云函数【searchHistory】报错!!!', e)
  }
}

cloudfunctions / recommendedKeywords / index.js

const cloud = require('wx-server-sdk')

cloud.init()

const db = cloud.database()
exports.main = async (event, context) => await db.collection('recommendedKeywords')
.orderBy('level', 'asc')
.limit(10)
.get()

cloudfunctions / removeExpiredSearchHistory / config.json

// 该定时触发器被设置成每天晚上23:00执行一次 index.js (删除3天前的数据)
{
  "triggers": [
    {
      "name": "remove expired search history",
      "type": "timer",
      "config": "0 0 23 * * * *"
    }
  ]
}

cloudfunctions / removeExpiredSearchHistory / index.js

const cloud = require('wx-server-sdk')

cloud.init()

const db = cloud.database()

const _ = db.command

let timeStamp = new Date().getTime()

// 删除3天前的数据
let duration = timeStamp - 1000 * 60 * 60 * 24 * 3

exports.main = async (event, context) => {
  try {
    let arr = await db.collection('searchHistory').where({
      timeStamp: _.lt(duration)
    }).get()

    let idArr = arr.data.map(v => v._id)
    console.log('idArr=', idArr)

    for (let i = 0; i < idArr.length; i++) {
      await db.collection('searchHistory').where({
        _id: idArr[i]
      }).remove()
    }
    
  } catch (e) {
    console.error(e)
  }
}

search.js 关键代码:

// 输入关键词,点击搜索

  tapSearch: function () {
    let that = this
    if (that.data.openid) {
      // 只为已登录的用户记录搜索历史
      that.tapSearchOrRecommended(that.data.keyword, that.data.openid)
    } else {
      // 游客直接跳转
      wx.navigateTo({
        url: `../goods-list/goods-list?keyword=${that.data.keyword}`,
      })
    }
  },

// 点击推荐的关键词

tabRecommended: function (e) {
  let that = this
  let keyword = e.currentTarget.dataset.keyword

  that.setData({
    keyword
  })

  if (that.data.openid) {
    // 只为已登录的用户记录搜索历史
    that.tapSearchOrRecommended(keyword, that.data.openid)
  } else {
    // 游客直接跳转
    wx.navigateTo({
      url: `../goods-list/goods-list?keyword=${keyword}`,
    })
  }
},

// 点击历史关键词

tabHistory: function (e) {
  let that = this
  let keyword = e.currentTarget.dataset.keyword

  wx.navigateTo({
    url: `../goods-list/goods-list?keyword=${keyword}`,
  })
  
  that.updateTimeStamp(keyword, that.data.openid)
},

// 获取历史记录和推荐

getHistoryAndRecommended: function () {
  let that = this

  try {
    // 只为已登录的用户获取搜索历史
    if (that.data.openid) {
      let searchHistoryNeedUpdate = app.globalData.searchHistoryNeedUpdate
      const searchHistory = wx.getStorageSync('searchHistory')

      // 如果本地有历史并且还没有更新的历史
      if (searchHistory && !searchHistoryNeedUpdate) {
        console.log('本地有搜索历史,暂时不需要更新')
        that.setData({
          searchHistory
        })
      } else {
        console.log('需要更新(或者本地没有搜索历史)')
        wx.cloud.callFunction({
          name: 'searchHistory',
          data: {
            type: 'getByOpenid',
            openid: that.data.openid
          },
          success(res) {
            console.log('云函数获取关键词记录成功')
            let searchHistory = []
            for (let i = 0; i < res.result.data.length; i++) {
              searchHistory.push(res.result.data[i].keyword)
            }
            that.setData({
              searchHistory
            })
            wx.setStorage({
              key: 'searchHistory',
              data: searchHistory,
              success(res) {
                console.log('searchHistory本地存储成功')
                // wx.stopPullDownRefresh()
                app.globalData.searchHistoryNeedUpdate = false
              },
              fail: console.error
            })
          },
          fail: console.error
        })
      }
    }

    // 获取推荐关键词
    wx.cloud.callFunction({
      name: 'recommendedKeywords',
      success(res) {
        console.log('云函数获取推荐关键词记录成功')
        let recommendedKeywords = []
        for (let i = 0; i < res.result.data.length; i++) {
          recommendedKeywords.push(res.result.data[i].keyword)
        }
        that.setData({
          recommendedKeywords
        })
      },
      fail: console.error
    })
    
  } catch (e) {
    fail: console.error
  }
},

// 添加该条新记录(tapSearchOrRecommended()要用到它两次)

addRecord: function (keyword, timeStamp) {
  let that = this
  // 【添加】
  wx.cloud.callFunction({
    name: 'searchHistory',
    data: {
      type: 'add',
      openid: that.data.openid,
      keyword,
      timeStamp
    },
    success(res) {
      console.log('云函数添加关键词成功')
      app.globalData.searchHistoryNeedUpdate = true
    },
    fail: console.error
  })
},

// 根据openid和keyword找出记录,并更新其时间戳

updateTimeStamp: function (keyword, openid) {
  this.setData({
    keyword
  })

  let timeStamp = new Date().getTime()

  wx.cloud.callFunction({
    name: 'searchHistory',
    data: {
      type: 'updateOfOpenidKeyword',
      openid,
      keyword,
      timeStamp,
    },
    success(res) {
      console.log('云函数更新关键词时间戳成功')
      app.globalData.searchHistoryNeedUpdate = true
    },
    fail: console.error
  })
},

// 输入关键词,点击搜索或者点击推荐的关键词

tapSearchOrRecommended: function (keyword, openid) {
  let that = this

  if (!keyword) {
    wx.showToast({
      icon: 'none',
      title: '请输入商品关键词',
    })
    setTimeout(function () {
      that.setData({
        isFocus: true
      })
    }, 1500)
    return false
  }

  wx.navigateTo({
    url: `../goods-list/goods-list?keyword=${keyword}`,
  })

  let timeStamp = new Date().getTime()

  // 【根据openid和keyword能否找出这条记录(count是否大于0)】
  wx.cloud.callFunction({
    name: 'searchHistory',
    data: {
      type: 'canFindIt',
      openid,
      keyword
    },
    success(res) {
      console.log('res.result.total=', res.result.total)
      if (res.result.total === 0) {
        // 集合中没有
        // 【根据openid查询当前记录条数】
        wx.cloud.callFunction({
          name: 'searchHistory',
          data: {
            type: 'countOfOpenid',
            openid
          },
          success(res) {
            // 记录少于10条
            if (res.result.total < 10) {
              // 【添加】
              that.addRecord(keyword, timeStamp)
            } else {
              // 【找出该openid下最早的一条记录】
              wx.cloud.callFunction({
                name: 'searchHistory',
                data: {
                  type: 'getEarliestOfOpenid',
                  openid
                },
                success(res) {
                  console.log('云函数找出最早的一条关键词成功', res.result.data[0])

                  let _id = res.result.data[0]._id

                  // 【根据最早记录的id,删除这条记录】
                  wx.cloud.callFunction({
                    name: 'searchHistory',
                    data: {
                      type: 'removeOfId',
                      _id
                    },
                    success(res) {
                      console.log('云函数删除最早的一条关键词成功')
                      // 【添加】
                      that.addRecord(keyword, timeStamp)
                    },
                    fail: console.error
                  })
                },
                fail: console.error
              })
            }

          },
          fail: console.error
        })
      } else {
        // 【根据openid和keyword找出记录,并更新其时间戳】
        that.updateTimeStamp(keyword, openid)
      }
    },
    fail: console.error
  })
}
最后一次编辑于  2019-03-28  
点赞 4
收藏
分享 评论
请 登录 后发表内容

PHP网站源码东莞百度关键词包年推广坂田品牌网站设计西乡网站优化排名坂田网站优化沙井百姓网标王吉祥英文网站建设大运设计网站布吉网站定制塘坑seo排名大芬建网站光明营销型网站建设南澳高端网站设计龙岗网站建设坪山网站改版吉祥百度seo惠州网络广告推广大运标王坂田企业网站设计南联外贸网站制作罗湖百度标王木棉湾网站搜索优化塘坑外贸网站设计松岗网站优化按天扣费坑梓设计公司网站木棉湾网站关键词优化西乡网站seo优化宝安网络推广大芬网站建设设计横岗百搜标王光明SEO按天收费歼20紧急升空逼退外机英媒称团队夜以继日筹划王妃复出草木蔓发 春山在望成都发生巨响 当地回应60岁老人炒菠菜未焯水致肾病恶化男子涉嫌走私被判11年却一天牢没坐劳斯莱斯右转逼停直行车网传落水者说“没让你救”系谣言广东通报13岁男孩性侵女童不予立案贵州小伙回应在美国卖三蹦子火了淀粉肠小王子日销售额涨超10倍有个姐真把千机伞做出来了近3万元金手镯仅含足金十克呼北高速交通事故已致14人死亡杨洋拄拐现身医院国产伟哥去年销售近13亿男子给前妻转账 现任妻子起诉要回新基金只募集到26元还是员工自购男孩疑遭霸凌 家长讨说法被踢出群充个话费竟沦为间接洗钱工具新的一天从800个哈欠开始单亲妈妈陷入热恋 14岁儿子报警#春分立蛋大挑战#中国投资客涌入日本东京买房两大学生合买彩票中奖一人不认账新加坡主帅:唯一目标击败中国队月嫂回应掌掴婴儿是在赶虫子19岁小伙救下5人后溺亡 多方发声清明节放假3天调休1天张家界的山上“长”满了韩国人?开封王婆为何火了主播靠辱骂母亲走红被批捕封号代拍被何赛飞拿着魔杖追着打阿根廷将发行1万与2万面值的纸币库克现身上海为江西彩礼“减负”的“试婚人”因自嘲式简历走红的教授更新简介殡仪馆花卉高于市场价3倍还重复用网友称在豆瓣酱里吃出老鼠头315晚会后胖东来又人满为患了网友建议重庆地铁不准乘客携带菜筐特朗普谈“凯特王妃P图照”罗斯否认插足凯特王妃婚姻青海通报栏杆断裂小学生跌落住进ICU恒大被罚41.75亿到底怎么缴湖南一县政协主席疑涉刑案被控制茶百道就改标签日期致歉王树国3次鞠躬告别西交大师生张立群任西安交通大学校长杨倩无缘巴黎奥运

PHP网站源码 XML地图 TXT地图 虚拟主机 SEO 网站制作 网站优化