Как вернуть элементы критериев соответствия массива в MongoDB - PullRequest
1 голос
/ 28 мая 2020

Я новичок в mongodb, и я все еще пытаюсь осмыслить запросы, так что простите меня, если мой вопрос слишком прост или я получил ответ в другом месте.

У меня есть коллекция, подобная приведенной ниже

[
{"_id":1,
"data" :[{"a":1,"b":2},{"a":1,"b":3},{"a":2,"b":3},{"a":4,"b":1}]
},
{"_id":2,
"data" :[{"a":3,"b":2},{"a":2,"b":4},{"a":5,"b":3},{"a":7,"b":1}]
}
]

Как мне написать запрос, который просматривает массив данных первого документа и возвращает все элементы, где «a» равно единице.

Примерно так вывод:

[{"a":1,"b":2},{"a":1,"b":3}]

Это моя текущая попытка

db.myCollection.find({_id:1},{data: {$elemMatch: {a : 1}}})

Но это дает мне

{"_id": 1, "data":
[{"a":1,"b":2},{"a":1,"b":3}]
}

Мне не нужно ничего, кроме результатов в «данных».

Может ли кто-нибудь помочь мне?

Я также был бы признателен за любые указатели для просеивания массива в документе для элементов, соответствующих более общим условиям в одном документе ( ie для приведенного выше примера поиск документов, в которых a + b <5, a> b, a> 1 и b> 2, a> 3 или b <1, et c.) </p>

Edit : Я использую mongodb версии 4.2.6

Ответы [ 2 ]

1 голос
/ 29 мая 2020

$filter - это универсальный способ фильтрации массивов внутри документов. Расширение набора входных данных, чтобы дать немного больше контекста и разнообразия:

var r =
[
 {
     "_id": 0,
     "other":6,
     "data" :[{"a":1,"b":2,"c":"X"},
              {"a":1,"b":3,"c":"Y"},
              {"a":2,"b":3,"c":"Q"},
              {"a":4,"b":1,"c":"Z"}]
 },
 {
     "_id": 1,
     "other":7,
     "data" :[{"a":1,"b":2,"c":"A"},
              {"a":1,"b":3,"c":"B"},
              {"a":7,"b":7,"c":"C"},
              {"a":1,"b":8,"c":"D"}]
 }
];
db.foo.insert(r);

Затем эти два конвейера демонстрируют универсальность $filter:

c = db.foo.aggregate([
{$project: {_id:false,
            // Notice input is $data and output project is data; this                     
            // means overwrite the old data array with the filtered array.                 
            // Also:  The double dollar is how we reference the "as"                      
            // variable.  Single dollar variables refer to the fields                     
            // of the incoming doc; we show how to use $other in this                     
            // example.   $other remains constant for the doc as $filter
            // marches down the $data array:                                                                 
            data: {$filter: {
                input: "$data",
                as: "z",
                cond: { $lt: [ {$add:["$$z.a","$$z.b"]} , "$other" ]}
            }}
    }}
                       ]);


c = db.foo.aggregate([
{$project: {_id:true,
            data: {$filter: {
                input: "$data",
                as: "z",
                cond: { $or: [ {$gt:["$$z.a",3]}, {$lt:["$$z.b",7]} ] }
            }}
    }}
                       ]);
1 голос
/ 28 мая 2020

У вас есть почти все, вы просто забываете проекцию в конце:

db.myCollection.find({_id:1},{data: {$elemMatch: {a : 1}}}, {_id: 0, data: 1})
...