【问题标题】:Mongo DB reverse an array field before slicingMongodb在切片前反转一个数组字段
【发布时间】:2020-10-06 23:39:07
【问题描述】:

我有这个 mongo 查询来获取线程中的消息列表。

await db
      .collection("threads")
      .find({
        _id: ObjectId(req.query.thread_id),
      })
      .project({
        messages: {
          $slice: [parseInt(req.query.offset), parseInt(req.query.limit)],
        },
        _id: 1,
        date_created: 1,
      })
      .toArray();

限制和偏移量由客户端设置以支持无限加载。问题是查询按它们添加的顺序获取结果,而它应该首先使用最后添加的消息进行分页。我该怎么做?是否有可能我可以在获取之前反转数组还是负载太大?

这是我的线程架构:

{
   "_id":{
      "$oid":"5f7b32c014014100176c2a55"
   },
   "thread_name":"personal",
   "messages":[
      {
         "_id":{
            "$oid":"5f7b32d414014100176c2a56"
         },
         "sender":{
            "$oid":"5f7b329114014100176c2a52"
         },
         "type":"text",
         "date_created":{
            "$date":"2020-10-05T14:51:00.716Z"
         },
         "content":"hi"
      },
      {
         "_id":{
            "$oid":"5f7b32df14014100176c2a57"
         },
         "sender":{
            "$oid":"5f7b329114014100176c2a52"
         },
         "type":"text",
         "date_created":{
            "$date":"2020-10-05T14:51:11.302Z"
         },
         "content":"hello"
      },
   ],
   "date_created":{
      "$date":"2020-10-05T14:50:40.271Z"
   },
}

【问题讨论】:

    标签: node.js database mongodb mongoose nosql


    【解决方案1】:

    您可以在聚合中使用$reverseArray 选项

    使用aggregate,您可以先使用$match(它将替换您的find 部分),然后使用$project,您可以添加新属性,如reversedMessages,您将在其中使用$reverseArray$slice结合

    所以,查询应该是这样的

    db.collection("threads").aggregate([
      {
        $match: {
          _id: ObjectId(req.query.thread_id),
        },
      },
      {
        $project: {
          _id: 1,
          date_created: 1,
          reverseMessages: {
            $slice: [
              { $reverseArray: "$messages" },
              0,
              parseInt(req.query.limit), // I guess you want to return latest n messages, where n is a limit from query
            ],
          },
        },
      },
    ]);
    

    【讨论】:

    • 并不总是最后 n 条消息,在某些情况下,用户滚动到最后并获取下一条消息。
    • 好吧,那么,您可以代替0,将其用作已加载消息的切片数的开始(我猜是offset),然后作为第二个参数做offset + limit,我猜限制是你想要获取的消息数
    • 由于某种原因,当我运行查询时,我得到了这个:MongoError: $slice array wrong size,它没有出现在上一个查询中。知道为什么吗?
    • 也许您提供的数字超出了数组的范围?因为,如果数组的长度为 10,并且您提供 $slice: [array, 1, 15],也许它会抛出错误?不太确定我在我拥有的一些收藏上对其进行了测试,它工作正常
    • 我基本上是从0开始的。数组的长度为 25+,我将限制设置为 5。
    【解决方案2】:

    “我可以在获取之前反转数组吗?”你无法扭转你没有的东西。我已经看到了$reverseArray 的另一个答案,但是当您可以只使用$slice 最后一个元素时,为什么还要花费资源来反转数组呢?

    如果为负,$slice 最多返回数组中的最后 n 个元素。如果指定了 n 则无法解析为负数

    db.collection("threads").aggregate([
      {
        $match: {
          _id: ObjectId(req.query.thread_id),
        },
      },
      {
        $project: {
          _id: 1,
          date_created: 1,
          reverseMessages: {
            $slice: [
              "$messages",
              parseInt(req.query.limit) * -1
            ]
          }
        }
      }
    ]);
    

    【讨论】:

    • 我并不总是想获取最后 n 条消息,有时我想从最后一页获取第二页,此时这是如何工作的?
    猜你喜欢
    • 2014-07-11
    • 2018-09-23
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-10-09
    • 1970-01-01
    • 2021-09-04
    • 2016-09-15
    相关资源
    最近更新 更多