MongoDB-如何在多个本地字段上进行$查找

suzh9iv8  于 2022-10-22  发布在  Go
关注(0)|答案(1)|浏览(115)

我必须在MongoDB中编写一个聚合查询,其中从源集合到目标集合的$lookup可以来自多个字段。即,源集合中的多个字段(所有ID)可以链接到目标集合中的单个字段。
换句话说,我的$lookup中的localfield有一个$or条件:
学生:

{
  "_id": : {
    "$oid": "61c32b08c6056d28db6550b5"
  },
  "name": "Jack Sparrow",
  "course1": : {
    "$oid": "82d77b08c6056d28db65ca98"
  },
  "course2": : {
    "$oid": "45d22b08c6056d28db688013"
  },
  "course3": : {
    "$oid": "98a72b08c6056d28db6561d6"
  },
  "course4": : {
    "$oid": "10b22b08c6056d28db6576b1"
  }
}

查询:

{
  $lookup: {
    'from': 'courses', 
    'localField': 'course1', 'course2', 'course3', 'course4' 
    'foreignField': '_id', 
    'as': 'studentCourses'
  }
}

本例中的源集合为students,目标集合为courses。源表中的课程数可以是最小值1和最大值4。这些值中的任何一个都可以与课程集合中的课程相关。
我怎样才能做到这一点呢?

jtoj6r0c

jtoj6r0c1#

localField只能支持string类型的值,表示字段名。
当您使用管道查找$lookup时,通过将那些course字段设置为courses数组,并在查找管道中使用$in运算符执行过滤。

db.students.aggregate([
  {
    $lookup: {
      "from": "courses",
      "let": {
        courses: [
          "$course1",
          "$course2",
          "$course3",
          "$course4"
        ]
      },
      "pipeline": [
        {
          $match: {
            $expr: {
              $in: [
                "$_id",
                "$$courses"
              ]
            }
          }
        }
      ],
      "as": "studentCourses"
    }
  }
])

Demo @ Mongo Playground

  • 观点:*

Thinking that your Student schema is not a good design. You may think how about the students may take a different number of courses. Possible that the referredcoursefield may not exist. Or you need to modify your query again if thecourse` field is added/removed each time.

You shall consider a m1n7o1p array field to store those m1n8o1p ids.`
您可以参考下面的查询,而不是硬编码字段名,而是获得带有前缀的字段的值:“Course”。

db.students.aggregate([
  {
    $lookup: {
      "from": "courses",
      "let": {
        courses: {
          $reduce: {
            input: {
              $filter: {
                input: {
                  $objectToArray: "$$ROOT"
                },
                cond: {
                  "$regexMatch": {
                    "input": "$$this.k",
                    "regex": "^course[\\d]$"
                  }
                }
              }
            },
            initialValue: [],
            in: {
              $concatArrays: [
                "$$value",
                [
                  "$$this.v"
                ]
              ]
            }
          }
        }
      },
      "pipeline": [
        {
          $match: {
            $expr: {
              $in: [
                "$_id",
                "$$courses"
              ]
            }
          }
        }
      ],
      "as": "studentCourses"
    }
  }
])

Demo 2 @ Mongo Playground

相关问题