Запитването на тази структура за желаните от вас резултати не е възможно без познаване на всички възможни forms
имена предварително и използването им в заявката. Във всеки случай би било много объркано. Въпреки това, прочетете, докато обяснявам как може да се направи.
Има проблем със структурата на тези документи, който ще ви попречи да правите разумен анализ на заявката. В настоящия момент ще трябва да знаете всички възможни полета за имена на формуляри, за да филтрирате нещо.
Текущата ви структура има формуляри, съдържащи поддокумент, от който всеки ключ съдържа друг поддокумент с едно свойство, status
. Това е трудно за преминаване като вашите forms
има произволна структура за всеки документ, който създавате. Това означава моделът за спускане към status
информация, която искате да сравните промените за всеки документ във вашата колекция.
Ето какво имам предвид под път. За да получите статус във всеки елемент, трябва да направите следното
Като вторият елемент се променя през цялото време. Няма начина към заместващ знак нещо подобно, тъй като наименуването се счита за изрично.
Това може да се смята за лесен начин за прилагане на сериализиране на данните от вашите формуляри но виждам по-гъвкав алтернатива. Това, от което се нуждаете, е структура на документа, която можете да обхождате по стандартен модел. Това винаги е нещо, което си струва да се вземе предвид при дизайна. Вземете следното:
{
"_id" : "Tvq444454j",
"name": "Jim",
"forms": [
{
"name": "Jorney",
"status":"closed"
},
{
"name": "Women",
"status":"void"
},
{
"name": "Child",
"status":"closed"
},
{
"name": "Farm",
"status":"closed"
}
]
}
Така че структурата на документа се променя, за да се направят forms
елемент масив и вместо да поставим полето за състояние под ключ, който наименува "полето на формуляр", имаме всеки член на масива като поддокумент, съдържащ "полето на формуляр" name
и status
. Така че както идентификаторът, така и състоянието все още са сдвоени заедно, но сега просто са представени като поддокумент. Това най-важно променя пътя за достъп до тези ключове, както сега за и двата името на полето и състоянието му, което можем да направим
Каквотова означава, че можете да търсите имената на всички полета във form
или цялото status
полета във form
или дори всички документи с определено name
поле и определен status
. Това е много по-добре от това, което може да се направи с оригиналната структура.
Сега във вашия конкретен случай искате да получите самосамо документите къдесички полетата не са void
. Сега няма начин в една заявка да направите това, тъй като няма оператор, който да сравнява всички елементи в масив по този начин и да види дали са еднакви. Но има два подхода, които можете да предприемете:
Първото и вероятно не толкова ефективно е да се прави заявка за всички документи, които съдържат елемент във forms
който има status
на "празнота". С получените идентификатори на документи можете да подадете друга заявка, която връща документите, които не имат посочените идентификатори.
db.forms.find({ "forms.status": "void" },{ _id: 1})
db.forms.find({ _id: $not: { $in: [<Object1>,<Object2>,<Object3>,... ] } })
Предвид размера на резултата това може да не е възможно и като цяло не е добра идея, тъй като операторът за изключване $not
основно налага пълно сканиране от колекцията, така че не можете да използвате индекс.
Друг подход е да използвате тръбопровода за агрегиране, както следва:
db.forms.aggregate([
{ "$unwind": "$forms" },
{ "$group": { "_id": "$_id", "status": { "$addToSet": "$forms.status" }}},
{ "$unwind": "$status" },
{ "$sort": { "_id": 1, "status": -1 }},
{ "$group": { "_id": "$_id", "status": { "$first": "$status"}}},
{ "$match":{ "status": "closed" }}
])
Разбира се, това ще върне само _id за съвпадащите документи, но можете да подадете заявка с $in и да върнете всички съответстващи документи. Това е по-добро от оператора за изключване, използван преди, и сега можем да използваме индекс, за да избегнем пълното сканиране на колекцията.
Като краен подход и за най-добрите съображение за производителност, можете да промените документа отново, така че на най-високо ниво да запазите „статуса“ дали някое поле във формулярите е „празно“ или „затворено“. Така че на най-високо ниво стойността ще бъде затворена само ако всички елементи са „затворени“ и „невалидни“, ако нещо е невалидно и т.н.
Това последно би означавало допълнителна програмна промяна и всички промени във forms
елементи ще трябва да актуализират и това поле, за да запазят "статуса". Това обаче е най-ефективният начин за намиране на документите, от които се нуждаете, и може да си заслужава вниманието.
РЕДАКТИРАНЕ :
Освен промяната на документа, за да има главен статус, най-бързият формуляр за заявка в преработената структура всъщност е:
db.forms.find({ "forms": { "$not": { "$elemMatch": { "status": "void" } } } })