【问题标题】:Array match in MongoDB lookup pipelineMongoDB 查找管道中的数组匹配
【发布时间】:2021-09-03 06:34:50
【问题描述】:

我有两个系列。一件艺术品,另一件收藏品(多件艺术品的专辑)。 每个艺术品都有一个“收藏”字段,该字段是一个数组,其中保存了它所属的收藏的 ID。

我想做的是获取用户的所有收藏以及每个收藏的前 4 幅作品(以在应用中显示预览)。

然而,这件事,我以为很简单,结果却变得更复杂了。

在普通查询中,我会这样做:

artworkModel.find({
    collections: collection
})

但是,在聚合管道中,这不起作用,因此我实施的解决方案是:

[
  {$match: {
      author: author,
    },
  },
  {
    $lookup: {
      from: 'artworks',
      as: 'previews',
      let: { collection: '$_id' },
      pipeline: [
        {
          $match: {
            collections: { $exists: true },
            $expr: { $in: ['$$collection', '$collections'] }, 
          },
        },
        { $sort: { date: -1 } },
        { $limit: 4 },
        { $addFields: { id: '$_id' } },
      ],
    },
  }
]

问题是我不能接受这个解决方案,因为它不像上面的查询那样使用“集合”字段上的索引,因此对集合执行全面扫描。感谢您的帮助。

编辑:样本数据

艺术品:

[
    {
      "_id": { "$oid": "612fa9541121d06014e7d9bc" },
      "collections": [
        { "$oid": "612fa9481121d06014e7d9b5" },
        { "$oid": "612fa9f6b2cc520a84e83dde" }
      ],
      "author": { "$oid": "5fe8fe53ff8d9dc25c9e3277" },
      "text": "Lorem ipsum dolor sit amet, consectetur adipiscing elit. Etiam vestibulum dolor id justo condimentum ",
      "type": "Text"
    },
    {
      "_id": { "$oid": "60eec90e787a0b320c514446" },
      "author": { "$oid": "5fe8fe53ff8d9dc25c9e3277" },
      "type": "Image",
      "asset": { "$oid": "60eec90e787a0b320c514441" },
      "collections": [{ "$oid": "612fa9f6b2cc520a84e83dde" }]
    },
    {
      "_id": { "$oid": "612fa9f2b2cc520a84e83db1" },
      "collections": [{ "$oid": "612fa9f6b2cc520a84e83dde" }],
      "author": { "$oid": "5fe8fe53ff8d9dc25c9e3277" },
      "text": "Lorem ipsum dolor sit amet",
      "type": "Text"
    },
    {
      "_id": { "$oid": "612549d4778270001862472f" },
      "author": { "$oid": "5fe8fe53ff8d9dc25c9e3277" },
      "type": "Video",
      "asset": { "$oid": "612549d4778270001862472a" }
    }
  ]
  

收藏:

[
  {
    "_id": { "$oid": "612fa9f6b2cc520a84e83dde" },
    "name": "Name",
    "author": { "$oid": "5fe8fe53ff8d9dc25c9e3277" },
    "itemsCount": 3,
  }
]

【问题讨论】:

  • 能否提供示例 json 数据?
  • @mohammad Naimi 感谢您的关注。我已经编辑了问题。
  • 示例数据中没有日期字段,假设集合有 1 个您忘记添加的日期字段,我猜
  • 是的,对不起,我没有意识到它在查询中被使用了。我已经简化了文档以提高可读性

标签: arrays mongodb mongoose aggregation-framework lookup


【解决方案1】:

我认为下面的查询与您的查询相同。 在运行它之前在artworks.collections(多键索引)上创建一个索引

查询

  • 根据作者过滤集合
  • 使用索引与普通查找连接
  • 与 1 个集合 [{}] 进行虚拟连接,仅用于应用管道 你想要的,这就像一个把戏

如果可以的话,测试一下,告诉我它是否有效,是否足够快

Test code here

db.collections.aggregate([
  {
    "$match": {
      "author": {
        "$eq": "5fe8fe53ff8d9dc25c9e3277"
      }
    }
  },
  {
    "$lookup": {
      "from": "artworks",
      "localField": "_id",
      "foreignField": "collections",
      "as": "previews"
    }
  },
  {
    "$lookup": {
      "from": "dummy",
      "let": {
        "previews": "$previews"
      },
      "pipeline": [
        {
          "$set": {
            "previews": "$$previews"
          }
        },
        {
          "$unwind": {
            "path": "$previews"
          }
        },
        {
          "$replaceRoot": {
            "newRoot": "$previews"
          }
        },
        {
          "$sort": {
            "date": -1
          }
        },
        {
          "$limit": 4
        },
        {
          "$set": {
            "id": "$_id"
          }
        },
        {
          "$unset": [
            "_id"
          ]
        }
      ],
      "as": "previews"
    }
  }
])

【讨论】:

  • 非常感谢您的贡献。但是,如果我正确理解代码,聚合首先“填充”所有艺术品,然后才将其限制为前 4 个。因此,理论上,如果集合包含许多艺术品,则查询会出现性能问题。我错过了什么吗?
  • 特定作者的所有集合首先会进入1个数组(只要是author中数组集合的成员),只要不是太多like就没有问题200.000 即使它们是 1000 我认为也很好。有了管道之前,我们只会逃避更大阵列的建设,我认为它不会花费很多。我没有数据来测试它或尝试替代方案,用你的数据试试,如果它很慢,我们会看到。
  • 对不起,我之前没有回复,但我现在才注意到,也许我的问题不清楚。我试图做的是从收藏中获取用户的所有收藏以及收藏中最近的四件艺术品。在这种情况下,您的聚合假定在用户的文档中有一个“收藏”字段,该字段不存在,但它在艺术品中。此外,即使我在艺术品收藏中运行查询,我也会得到艺术品及其收藏。但是,我需要这些收藏品,并且每个收藏品都有 4 件艺术品。也许我不明白你的解决方案。
  • 别担心我做了与你想要的相反的连接,我现在修复了它,我想现在和你的查询一样,如果你有很多数据,如果你可以比较这两个,请发送一些反馈查询(不要忘记在artworks.collections 上创建多键索引),我很好奇它是否有帮助,gl
猜你喜欢
  • 2020-06-13
  • 2023-02-25
  • 1970-01-01
  • 1970-01-01
  • 2020-07-27
  • 1970-01-01
  • 1970-01-01
  • 2017-08-06
  • 2018-01-21
相关资源
最近更新 更多