【问题标题】:How to do a conditional $lookup in MongoDB如何在 MongoDB 中进行条件 $lookup
【发布时间】:2021-10-11 10:56:38
【问题描述】:

我有三个集合:A、B、C。

A 有一个名为 a 的属性,它是 B 或 C 中的一个 ref id。

我要做的是,先在B中查找,如果没有找到,然后在C中查找。

类似这样的:

[
    {
        $lookup: 
        {
            from: 'B',
            localField: 'a',
            foreignField: '_id',
            as: 'temp'
        }
    },
    { 
        $unwind: 
        {
            path: '$temp', 
            preserveNullAndEmptyArrays: true 
        }
    },
    {
        $lookup: 
        {
            if: 'temp not exist',      <! just demonstrate !>
            from: 'C',
            localField: 'a',
            foreignField: '_id',
            as: 'temp'
        }
    },
]

我不知道如何实现。有人可以帮忙吗?谢谢。

【问题讨论】:

  • 请提供每个集合的样本数据

标签: mongodb lookup


【解决方案1】:

根据查询运行时我们拥有的信息,我认为我们不能执行条件管道阶段(我们可以执行条件运算符但不能执行阶段)。

*如果我们在编写查询时获得信息,我们可以动态生成查询并包含或不包含阶段

但是您可以将$lookup 与管道一起使用,并添加此过滤器,例如如果 temp 为空数组(表示未发生连接),则仅在那时加入。

我看不出有理由在中间进行放松,进行 2 次查找并在之后进行。

查询

  • 进行第一次查找
  • 第二次查找是带有过滤器的管道,要求第一次查找临时数组为空
    (如果您在中间保持放松,请使用 {"$eq": [{"$type": "$temp"}, "missing"]} 而不是空支票)
  • 保持为 temp,temp 或 tempC 取决于谁不为空
  • 取消设置 tempC
  • 现在是否展开(我认为在展开之前加入更快,文件更少),您还想先找到加入成员然后展开
aggregate(
[ {"$lookup": 
    {"from": "B", "localField": "a", "foreignField": "_id", "as": "temp"}},
  {"$lookup": 
    {"from": "C",
      "let": {"a": "$a", "temp": "$temp"},
      "pipeline": 
      [{"$match": 
          {"$expr": 
            {"$and": [{"$eq": ["$temp", []]}, {"$eq": ["$a", "$_id"]}]}}}],
      "as": "tempC"}},
  {"$set": {"temp": {"$cond": [{"$eq": ["$temp", []]}, "$tempC", "$temp"]}}},
  {"$unset": ["tempC"]},
  {"$unwind": {"path": "$temp", "preserveNullAndEmptyArrays": true}}])

【讨论】:

  • 非常感谢。据我了解,它将在 B 和 C 集合中搜索。但实际上这不是必需的,并且可能会花费额外的时间。如果第一次搜索已经返回了一些东西,我们有什么可以跳过第二次搜索的解决方案吗?
  • 我对它进行了基准测试,MongoDB 即使您放置了一个始终为假的过滤器,它只需要管道中的集合字段(而不是其他集合),您仍然需要支付 75% 的查找成本,MongoDB没有优化,我希望它会但它没有。上面的代码做你想做的事,但你不能完全避免查找的成本。
猜你喜欢
  • 2020-05-11
  • 2021-12-06
  • 1970-01-01
  • 2022-07-09
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2020-09-07
  • 2016-11-14
相关资源
最近更新 更多