Агрегация по разным коллекциям (внешний ключ) - агрегация MongoDB - PullRequest
1 голос
/ 11 апреля 2020

Учитывая, что у меня есть 2 коллекции .

Первая, названная origin, имеет следующие документы (исключая _id):

Происхождение

[
  {
    "Id": "1",
    "Level1": [
      {
        "Id": "1.1",
        "Level2": [
          {
            "Level3": {
              "Id": "1.1.1",
              "Name": "name 1.1.1"
            }
          },
          {
            "Level3": {
              "Id": "1.1.2",
              "Name": "name 1.1.2"
            }
          }
        ]
      },
      {
        "Id": "1.2",
        "Level2": [
          {
            "Level3": {
              "Id": "1.2.1",
              "Name": "name 1.2.1"
            }
          },
          {
            "Level3": {
              "Id": "1.2.2",
              "Name": "name 1.2.2"
            }
          }
        ]
      }
    ]
  },
  {
    "Id": "2",
    "Level1": [
      {
        "Id": "2.1",
        "Level2": [
          {
            "Level3": {
              "Id": "2.1.1",
              "Name": "name 2.1.1"
            }
          },
          {
            "Level3": {
              "Id": "2.1.2",
              "Name": "name 2.1.2"
            }
          }
        ]
      },
      {
        "Id": "2.2",
        "Level2": [
          {
            "Level3": {
              "Id": "2.2.1",
              "Name": "name 2.2.1"
            }
          },
          {
            "Level3": {
              "Id": "2.2.2",
              "Name": "name 2.2.2"
            }
          }
        ]
      }
    ]
  }
]

Вторая коллекция называется destination и содержит следующие документы:

Направление

[
  {
    "Id": "f1",
    "Level1": {
      "Level2": {
        "Id": "1.1.1",
        "Name": "name 1.1.1"
      }
    }
  },
  {
    "Id": "f2",
    "Level1": {
      "Level2": {
        "Id": "1.1.2",
        "Name": "name 1.1.2"
      }
    }
  },
  {
    "Id": "f3",
    "Level1": {
      "Level2": {
        "Id": "1.2.1",
        "Name": "name 1.2.1"
      }
    }
  },
  {
    "Id": "f4",
    "Level1": {
      "Level2": {
        "Id": "1.2.2",
        "Name": "name 1.2.2"
      }
    }
  },
  {
    "Id": "f5",
    "Level1": {
      "Level2": {
        "Id": "2.1.1",
        "Name": "name 2.1.1"
      }
    }
  },
  {
    "Id": "f6",
    "Level1": {
      "Level2": {
        "Id": "2.1.2",
        "Name": "name 2.1.2"
      }
    }
  },
  {
    "Id": "f7",
    "Level1": {
      "Level2": {
        "Id": "2.2.1",
        "Name": "name 2.2.1"
      }
    }
  },
  {
    "Id": "f8",
    "Level1": {
      "Level2": {
        "Id": "2.2.2",
        "Name": "name 2.2.2"
      }
    }
  }
]

Запрос

Level1.Id = "1.1" на origin


Logi c

Учитывая Level1.Id = "1.1" на origin собрание, я хочу получить список документов из destination собрание, где:

Level1.Level2.Level3 in origin = Level1.Level2 in destination

Запрос агрегации из origin должен "собрать" все объекты Level1.Level2.Level3 (под соответствующим Level1.Id) и использовать этот массив для идентификации документов в коллекции destination.


Ожидаемый результат:

Результат

[
  {
    "Id": "f1",
    "Level1": {
      "Level2": {
        "Id": "1.1.1",
        "Name": "name 1.1.1"
      }
    }
  },
  {
    "Id": "f2",
    "Level1": {
      "Level2": {
        "Id": "1.1.2",
        "Name": "name 1.1.2"
      }
    }
  }
]

Как мне сделать sh это с запросом агрегации?

1 Ответ

1 голос
/ 11 апреля 2020

В MongoDB для агрегации данных из разных коллекций мы используем для этого $lookup, подробнее о поиске здесь .

Я выполнил запрос поиска в соответствии с вашими требованиями.

db.origin.aggregate([
  {
    $unwind:"$Level1"
  },
  {
    $unwind:"$Level1.Level2"
  },
  {
    $lookup:{
      from:"destination",
      let:{
        "level":"$Level1.Level2.Level3"
      },
      pipeline:[
        {
          $match:{
            $expr:{
              $eq:[
                "$Level1.Level2","$$level"
              ]
            }
          }
        }
      ],
      as:"lookups"
    }
  },
  {
    $unwind:{
      path:"$lookups",
      preserveNullAndEmptyArrays:true
    }
  }
]).pretty()

И, для отображения полей, которые вы хотите в выводе, вы можете использовать $project. Подробнее читайте здесь .

Надеюсь, это поможет вам:)

ОБНОВЛЕНИЕ

db.destination.aggregate([
  {
    $lookup:{
      from:"origin",
      let:{
        "level":"$Level1.Level2"
      },
      pipeline:[
        {
          $unwind:"$Level1"
        },
        {
          $unwind:"$Level1.Level2"
        },
        {
          $match:{
            $expr:{
              $eq:[
                "$Level1.Level2.Level3","$$level"
              ]
            }
          }
        }
      ],
      as:"lookups"
    }
  },
  {
    $unwind:{
      path:"$lookups",
      preserveNullAndEmptyArrays:true
    }
  },
  {
    $project:{
      "Id":1,
      "Level1.Level2":"$lookups.Level1.Level2.Level3"
    }
  }
]).pretty()

Вывод

[
        {
                "_id" : ObjectId("5e92196a3a5a7fc48b644f67"),
                "Id" : "f1",
                "Level1" : {
                        "Level2" : {
                                "Id" : "1.1.1",
                                "Name" : "name 1.1.1"
                        }
                }
        },
        {
                "_id" : ObjectId("5e92196a3a5a7fc48b644f68"),
                "Id" : "f2",
                "Level1" : {
                        "Level2" : {
                                "Id" : "1.1.2",
                                "Name" : "name 1.1.2"
                        }
                }
        },
        {
                "_id" : ObjectId("5e92196a3a5a7fc48b644f69"),
                "Id" : "f3",
                "Level1" : {
                        "Level2" : {
                                "Id" : "1.2.1",
                                "Name" : "name 1.2.1"
                        }
                }
        },
        {
                "_id" : ObjectId("5e92196a3a5a7fc48b644f6a"),
                "Id" : "f4",
                "Level1" : {
                        "Level2" : {
                                "Id" : "1.2.2",
                                "Name" : "name 1.2.2"
                        }
                }
        },
        {
                "_id" : ObjectId("5e92196a3a5a7fc48b644f6b"),
                "Id" : "f5",
                "Level1" : {
                        "Level2" : {
                                "Id" : "2.1.1",
                                "Name" : "name 2.1.1"
                        }
                }
        },
        {
                "_id" : ObjectId("5e92196a3a5a7fc48b644f6c"),
                "Id" : "f6",
                "Level1" : {
                        "Level2" : {
                                "Id" : "2.1.2",
                                "Name" : "name 2.1.2"
                        }
                }
        },
        {
                "_id" : ObjectId("5e92196a3a5a7fc48b644f6d"),
                "Id" : "f7",
                "Level1" : {
                        "Level2" : {
                                "Id" : "2.2.1",
                                "Name" : "name 2.2.1"
                        }
                }
        },
        {
                "_id" : ObjectId("5e92196a3a5a7fc48b644f6e"),
                "Id" : "f8",
                "Level1" : {
                        "Level2" : {
                                "Id" : "2.2.2",
                                "Name" : "name 2.2.2"
                        }
                }
        }
]
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...