Mongodb: поиск в массиве с $ aggregate - PullRequest
0 голосов
/ 17 апреля 2020

У меня 2 коллекции. Документы выглядят следующим образом. Для облегчения понимания я удалил другие свойства:

Collection_A

{
    "ref_id" : ObjectId("5e9561edf8beb57100dded8f"),
    "features" : [
        {
            "_id" : ObjectId("5e9561edf8beb57100dded91"),
            "k" : "foo",
            "v" : "bar"
        },
        {
            "_id" : ObjectId("5e9561edf8beb57100dded92"),
            "k" : "foo2",
            "v" : "bar2"
        }
    ]
}

Collection_B

{
    "ref_id" : ObjectId("5e9561edf8beb57100dded8f")
}

Используя агрегат, я пытаюсь найти все документы в Collection_B, где Collection_B.ref_id == Collection_A.ref_id and Collection_A.features == [{k:foo,v:bar},{k:foo2,v:bar2}]

В основном сопоставить предоставленный массив функций с $ Collection_A.features. Агрегат должен возвращать документ, когда все предоставленные функции присутствуют в $ Collection_A.features.

После попытки это самое близкое, что у меня есть:

let aggregation_queries = [];

aggregation_queries.push({
     $lookup: {
        from: "Collection_A",
        localField: "ref_id",
        foreignField: "ref_id",
        as: "Collection_A"
       }
});

 for(let i = 0; i< features.length; i++)
 {
   aggregation_queries.push({$match: { $expr: { $in : [features[i].k, "$Collection_A.features.k" ]}}});
 }

let aggregateResult = Collection_BSchema.aggregate(aggregation_queries);

Это соответствует только functions.k, но не функциям .в. Я пытаюсь найти способ сопоставления как fetaures.k, так и features.v, например, $ и: [{features [i] .k, "$ Collection_A.features.k"}, {features [i] .v, "$ Collection_A.features.v"}]

Я искал и пробовал множество подходов, таких как $ match с $ all, но, похоже, не работает, потому что match не поддерживает $ all для ex: " $ match ": {" $ expr ": {" $ all ": [" $ Collection_A.features ", features]}, который выдает ошибку" Ошибка: нераспознанное выражение '$ all'MongoError: Нераспознанное выражение ".

Может кто-нибудь помочь с этим или дать руководство?

Ответы [ 2 ]

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

@ Whoami. Это сработало:

db.Collection_B.aggregate([
  {
    $lookup: {
      from: "Collection_A",
      let: {
        refId: "$ref_id"
      },
      pipeline: [
        {
          $match: {
            $expr: {
              $eq: [
                "$ref_id",
                "$$refId"
              ]
            }
          }
        },
        {
          "$match": {
            "features": {
              $all: [
                {
                  "$elemMatch": {
                    "k": "foo",
                    "v": "bar"
                  }
                },
                {
                  "$elemMatch": {
                    "k": "foo2",
                    "v": "bar2"
                  }
                }
              ]
            }
          }
        }
      ],
      as: "Collection_A"
    }
  }
])
0 голосов
/ 17 апреля 2020

В вашем запросе есть несколько изменений, так как вы агрегируете на Collection_B и хотите присоединиться к Collection_B & Collection_A, затем в $lookup измените from: "Collection_B" на from: "Collection_A". Теперь вы можете использовать агрегационный конвейер в $ lookup , который может принять несколько условий перед получением соответствующего документа из Collection_A в lookup поле результата Collection_A из Collection_B документа:

Collection_BSchema.aggregate([
  {
    $lookup: {
      from: "Collection_A",
      let: { refId: "$ref_id" },
      pipeline: [
        { $match: { $expr: { $eq: ["$ref_id", "$$refId"] } } },
        { $match: { features: { $elemMatch: { k: "foo", v: "bar" } } } },
      ],
      as: "Collection_A",
    },
  },
]);

Тест: MongoDB-Playground

...