首页 > 解决方案 > 如何在 MongoDB 中进行条件 $lookup

问题描述

我有三个系列: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'
        }
    },
]

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

标签: mongodblookup

解决方案


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

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

但是你可以使用$lookup管道,并添加这个过滤器,比如如果 temp 是空数组(意味着没有发生连接),然后才加入。

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

询问

  • 进行第一次查找
  • 第二个查找是带有过滤器的管道,它要求第一个查找临时数组为空
    (如果您将展开保持在中间,请使用它{"$eq": [{"$type": "$temp"}, "missing"]}而不是空检查)
  • 保持为 temp,temp 或 tempC 取决于谁不为空
  • 取消设置温度C
  • 现在放松(我认为在放松之前加入更快,它的文件更少),你也想先找到加入成员然后放松
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}}])

推荐阅读