MongoDB $lookup如果本地字段存在

lo8azlld  于 2023-06-05  发布在  Go
关注(0)|答案(3)|浏览(310)

我有这些实体:

// collectionA
{
  key: "value",
  ref: SOME-OBJECT-ID
}

// collectionB
{
  _id: SOME-OBJECT-ID
  key1: "value1"
}

我希望如果ref存在于collectionA实体中,它将在collectionB上查找它并带来它的数据。
如果ref键丢失或没有丢失但collectionB中的实体丢失,则我从所有聚合查询中获得空结果。
这是聚合查询:

{ $match },
{
  $lookup: {
    from: "collectionB",
    let: {
      ref: "$ref"
    },
    pipeline: [
      {
        $match: {
          $expr: {
            $eq: [
              "$_id", "$$ref"
            ]
          }
        }
      },
      {
        $project: {
          key1: 1
        }
      }
    ],
    as: "someData"
  }
}

如何避免这种情况或添加任何条件$lookup?

f0brbegy

f0brbegy1#

一种方法是在开始处添加另一个match,以跳过source
要跳过B,可以在末尾省略。

{$match:{ ref:{$exists:true}}}

它将只考虑ref现有文档。
play

db.A.aggregate([
  {
    "$match": {
      ref: {
        $exists: true
      }
    }
  },
  {
    "$lookup": {
      "from": "B",
      "localField": "ref",
      "foreignField": "_id",
      "as": "output"
    }
  }
])

但如果没有特定的用例,则不需要这样做,因为它不会产生太大影响。

tpgth1q7

tpgth1q72#

我找到了文档没有被选中,因为我使用了$unwind-如果我们试图在空数组上执行此操作,它将不会返回文档。这就是解决办法

{
  $unwind: {
    path: "$ref",
    preserveNullAndEmptyArrays: true
  }
}

而不是:

{
  $unwind: "$ref"
}

我从这个答案中找到了preserveNullAndEmptyArraysHow to get all result if unwind field does not exist in mongodb

axr492tv

axr492tv3#

如果本地字段不存在,则应该在lookup的子查询管道中匹配零个文档。可以通过使用$cond操作符并将null传递给$match stage(如果字段不存在,则$type操作符返回'missing')来实现:

{
  $lookup: {
    from: 'collectionB',
    let: {
      ref: '$ref'
    },
    pipeline: [
      {$match: {
        $expr: {
          $cond: {
            if: { $eq: [{ $type: "$$ref" }, "missing"] },
            then: {$literal: null},
            else: {$eq: ['$_id', '$$ref']}
          }
        }
      }}
    ],
    as: 'someData'
  }
}

一个相关的答案是here

相关问题