MongoDB
 sql >> база данни >  >> NoSQL >> MongoDB

рамка за агрегиране на mongodb съвпадение чрез вложени документи

Запитването на тази структура за желаните от вас резултати не е възможно без познаване на всички възможни 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" } } } })



  1. Redis
  2.   
  3. MongoDB
  4.   
  5. Memcached
  6.   
  7. HBase
  8.   
  9. CouchDB
  1. Неуспешно свързване на Mongoose с Atlas

  2. Отидете:Създайте io.Writer интерфейс за регистриране в базата данни mongodb

  3. Как да премахнете дублиращи се записи от масив?

  4. Как да mongoexport с едно поле

  5. Ръководство за разработчици за MongoDB Sharding