MongoDB — Как сравнить поля разных коллекций в $ match агрегата?

#mongodb

#mongodb

Вопрос:

Предположим, у меня есть коллекция A и коллекция B . Мой запрос выглядит следующим образом:

 db.A.aggregate([
    {
       $lookup: {
           from: "B",
           localField: "_id",
           foreignField: "custom_id",
           as: "B"
        }
    },
    {
     $match: {
           "B.anotherId": "A.anotherId" // not working, is it possible?
    }
])
 

Мне любопытно узнать, возможно ли сделать то, что я пытался сделать $match . Цель состоит в том, чтобы получить только те документы, которые имеют одинаковое значение «anotherId» в документах A и B. Поддерживается ли это? И если да, то как с этим поступить?

Комментарии:

1. опубликуйте свои образцы документов для обеих коллекций и ожидаемого результата,

2. @turivishal часть $lookup в порядке, _id — это локальное поле (A), а custom_id — это внешнее поле (B). «anotherId» — это просто еще одно поле в обеих коллекциях.

Ответ №1:

Вы можете использовать $lookup с конвейером агрегации,

  • let чтобы определить ваши оба поля и проверить условие выражения в $match и $and
 db.A.aggregate([
    {
        $lookup: {
            from: "B",
            let: {
                custom_id: "$_id",
                anotherId: "$anotherId
            },
            pipeline: [
                {
                    $match: {
                        $expr: {
                            $and: [
                                { $eq: ["$custom_id", "$custom_id"] },
                                { $eq: ["$anotherId", "$anotherId"] }
                            ]
                        }
                    }
                }
            ],
            as: "B"
        }
    }
])
 

Комментарии:

1. это отфильтрует и даст вам только совпадения в B @ Bob. То же самое, что сделал бы $ filter в моем ответе выше.

Ответ №2:

Не уверен, чего вы пытаетесь достичь здесь. $lookup предоставляет массив значений. Вы пытаетесь отфильтровать массив? Это означало бы, что вам нужно использовать $filter. Однако, исходя из вашего вопроса о том, как сравнить два поля, вы должны использовать $expr .

 {
     $match: {
        $expr: {
            $eq: ["$firstField", "$secondField"]
       }
    }
}
 

Однако, если вы пытаетесь отфильтровать коллекцию B на основе значения в A, вам придется использовать $filter

 {
   $set: {
      B: {
         $filter: {
             input: "$B",
             as: "b",
             cond: {
                $eq: ["$A.anotherId", "$b.anotherId"]
             }
         }
      }

   }
}
 

Комментарии:

1. Привет, спасибо за ваш ответ. Могу ли я использовать A.fieldInADocument вместо $firstField и B.fieldInBDocument вместо $secondField?

2. Я имею в виду, в моем случае было бы: $ eq: [«B.anotherId»: «A.anotherId»]?

3. Ваша потребность больше похожа на $ filter из B, а не на прямое совпадение. предположим, что B имеет более одного значения «anotherId» в A, тогда сопоставление с $ expr просто вернет A со всеми значениями в B. И если B не имеет совпадения, то $expr не даст никаких результатов. $filter — это способ перейти к файлу B с совпадениями. Если вы можете создать образец документов в A и B и ваши ожидаемые результаты, это поможет.