首页 > 解决方案 > 有没有更好的方法在 mongodb 文档中的索引之后对数组字段进行切片?

问题描述

我的文档中有一个订单字段,其中包含另一个集合中文档的参考 ID。

product: {
  _id: // product id,
  orders: [refId_1415, refId_5414, refId_0210, refId_4320, refId_1543, refId_4326, refId_7845]
}

由于它们不是按升序/降序排列的,因此我无法真正运行 $gt 或 $lt 来检索值。因此,我必须在用户给出某个 refId 之后获取所有 refId。假设 refId_5414 是用户给出的。因此,从索引 2 (refId_0210) 开始运行 $lookup 以返回一个数组,其中填充的值如下所示:

order_history: [{
  id: refId_0210,
  created: // Date
}, 
{
  id: refId_4320,
  created: // Date
},
  ...
{ 
  id: refId_7845,
  created: // Date
}];

这是我提出的查询并且它有效,但是有很多阶段,我想知道是否有更好的方法来做到这一点:

  1. 查找具有 id 的产品。
{
  $match: { _id: product._id }, 
},
  1. 找到所需起始索引之前的 id 索引,因为这就是我们将收到的。
{
  $project: {
    index: {
      $indexOfArray: ["$orders", "refId_5414"],
    },
    orders: 1,
  },
},
  1. 将上一阶段的索引增加 1 以获得所需的起始索引。
{
  $project: {
    index: { $add: ["$index", 1] },
    orders: 1,
  },
},
  1. 将数组从起始索引切片到给定索引。
{
  $project: {
    orders: { $slice: ["$orders", "$index", to] },
    _id: 0,
  },
},
  1. 重新填充数组
{
  $lookup: {
    from: "orders",
    let: { orders: "$orders" },
    pipeline: [{ $match: { $expr: { $in: ["$_id", "$$orders"] } } }],
    as: "order_history",
  },
},

这是它的外观(注意 3 个项目阶段):

const res = await this.collection.aggregate([
  {
    $match: { _id: product._id },
  },
  {
    $project: {
      ...
    },
  },
  {
    $project: {
      ...
    },
  },
  {
    $project: {
      ...
    },
  },
  {
    $lookup: {
    ...
    },
  },
])

任何使它变得更好的建议将不胜感激。谢谢你。

标签: mongodbaggregation-framework

解决方案


您的查询看起来不错,您可以减少多个$project阶段并使用简单的查找:

  { $match: { _id: 1 } },
  {
    $project: {
      _id: 0,
      orders: {
        $slice: [
          "$orders",
          {
            $add: [
              { $indexOfArray: ["$orders", "refId_5414"] },
              1
            ]
          },
          to
        ]
      }
    }
  },
  {
    $lookup: {
      from: "orders",
      localField: "orders",
      foreignField: "id",
      as: "orders"
    }
  },
  { $project: { orders: "$orders.id" } }

操场


推荐阅读