评论

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

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

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

效果图如下:

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

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
收藏
评论
登录 后发表内容