Подсчет агрегации вложенных объектов MongoDB
у меня есть высоко вложенный набор объектов mongoDB, и я хочу подсчитать количество вложенных документов, которые соответствуют заданному условию Edit: (в каждом документе). Например:
{"_id":{"chr":"20","pos":"14371","ref":"A","alt":"G"},
"studies":[
{
"study_id":"Study1",
"samples":[
{
"sample_id":"NA00001",
"formatdata":[
{"GT":"1|0","GQ":48,"DP":8,"HQ":[51,51]}
]
},
{
"sample_id":"NA00002",
"formatdata":[
{"GT":"0|0","GQ":48,"DP":8,"HQ":[51,51]}
]
}
]
}
]
}
{"_id":{"chr":"20","pos":"14372","ref":"T","alt":"AA"},
"studies":[
{
"study_id":"Study3",
"samples":[
{
"sample_id":"SAMPLE1",
"formatdata":[
{"GT":"1|0","GQ":48,"DP":8,"HQ":[51,51]}
]
},
{
"sample_id":"SAMPLE2",
"formatdata":[
{"GT":"1|0","GQ":48,"DP":8,"HQ":[51,51]}
]
}
]
}
]
}
{"_id":{"chr":"20","pos":"14373","ref":"C","alt":"A"},
"studies":[
{
"study_id":"Study3",
"samples":[
{
"sample_id":"SAMPLE3",
"formatdata":[
{"GT":"0|0","GQ":48,"DP":8,"HQ":[51,51]}
]
},
{
"sample_id":"SAMPLE7",
"formatdata":[
{"GT":"0|0","GQ":48,"DP":8,"HQ":[51,51]}
]
}
]
}
]
}
Я хочу знать, сколько вложенных документов содержит GT: "1/0", который в этом случае будет 1 в первом документе, и два во втором, и 0 в 3-м. Я пробовал функции unwind и aggregate, но я, очевидно, не делаю что-то правильное. Когда я пытаюсь подсчитать документы sub по полю " GT " монго жалуется:
db.collection.aggregate([{$group: {"$studies.samples.formatdata.GT":1,_id:0}}])
поскольку имена моей группы не могут содержать ".- но если я их опущу ... --6-->
db.collection.aggregate([{$group: {"$GT":1,_id:0}}])
он жалуется, потому что "$GT не может быть именем оператора"
какие идеи?
1 ответов
вам нужно $unwind
при работе с массивами, и вам нужно сделать это три раза:
db.collection.aggregate([
// Un-wind the array's to access filtering
{ "$unwind": "$studies" },
{ "$unwind": "$studies.samples" },
{ "$unwind": "$studies.samples.formdata" },
// Group results to obtain the matched count per key
{ "$group": {
"_id": "$studies.samples.formdata.GT",
"count": { "$sum": 1 }
}}
])
В идеале вы хотите отфильтровать свой вход. Возможно, сделайте это с помощью $match как до, так и после $unwind обрабатывается и использует $регулярное выражение для сопоставления документов, где данные в точке начинается с "1".
db.collection.aggregate([
// Match first to exclude documents where this is not present in any array member
{ "$match": { "studies.samples.formdata.GT": /^1/ } },
// Un-wind the array's to access filtering
{ "$unwind": "$studies" },
{ "$unwind": "$studies.samples" },
{ "$unwind": "$studies.samples.formdata" },
// Match to filter
{ "$match": { "studies.samples.formdata.GT": /^1/ } },
// Group results to obtain the matched count per key
{ "$group": {
"_id": {
"_id": "$_id",
"key": "$studies.samples.formdata.GT"
},
"count": { "$sum": 1 }
}}
])
обратите внимание, что во всех случаях префиксные записи "доллар $" являются " переменными" ссылка на свойства документа. Это "значения" для использования ввода с правой стороны. Левая сторона "keys" должна быть указана как простая строковая клавиша. Никакая переменная не может использоваться для имени ключа.