Поиск массива объектов MongoDB, где свойство имеет одинаковое значение для более чем 1 элемента массива

У меня есть коллекция продуктов Mongo с полем «Категории», которое представляет собой массив объектов.

{
    "_id" : ObjectId("XXX"),
    "title" : "Cool Product",
    "details" : "Some Details",
    "categories" : [ 
        {
            "name" : "Cat1",
            "isPrimary" : true
        }, 
        {
            "isPrimary" : true,
            "name" : "Cat2"
        }, 
        {
            "name" : "Cat3"
        }
    ]
}

Поскольку продукт может иметь более одной категории, я хотел принудительно установить отношение первичной категории (один к одному). Однако при переносе данных в некоторых документах свойство isPrimary имеет значение true для нескольких категорий в документе. Мне нужно найти продукты, где isPrimary истинно для более чем одного элемента массива в массиве категорий. Это то, что у меня есть до сих пор:

db.products.find({ "categories" : { "$elemMatch" : { "isPrimary" : { "$exists" : false}}}})

Но это дает мне только те результаты, где isPrimary не существует для одного из элементов массива. Я не могу понять, как запросить isPrimary с одинаковым значением для нескольких элементов массива. Кроме того, это также будет запрос Spring:

Query query = new Query();
query.addCriteria(new Criteria().orOperator(
            Criteria.where("categories").elemMatch(Criteria.where("isPrimary").exists(false)),
            Criteria.where("categories").size(0),
            Criteria.where("categories")
            ));
query.with(new Sort(Sort.Direction.ASC, "title"));
return operations.find(query, Product.class);

person jth_92    schedule 14.03.2015    source источник


Ответы (1)


Здесь вам нужно использовать конвейер агрегации:

db.products.aggregate([
 {$unwind:"$categories"},
 {$match:{"categories.isPrimary":true}},
 {$group:{_id:"$_id", numPrimaries:{$sum:1}}},
 {$match:{numPrimaries:{$gt:1}}}
])

Это «раскрутит» массив категорий, сохранит только те, у которых значение isPrimary истинно, «перемотает» или сгруппирует их обратно по исходному _id, суммируя, сколько значений isPrimary было истинным, а затем отфильтрует документы, в которых было только одно. У вас останутся значения _id документов, которые имели несколько категорий с isPrimary true.

person Asya Kamsky    schedule 14.03.2015