sql >> Databáze >  >> NoSQL >> MongoDB

shoda agregačního rámce mongodb podle vnořených dokumentů

Dotazování této struktury na požadované výsledky není možné bez znalosti všech možných forms jména předem a jejich použití v dotazu. V každém případě by to bylo velmi chaotické. To znamená, že čtěte dál, když vysvětluji, jak to lze provést.

Existuje problém se strukturou těchto dokumentů, který vám zabrání v provádění jakékoli rozumné analýzy dotazů. V současné době byste museli znát všechna možná pole názvů formuláře, abyste mohli cokoli odfiltrovat.

Vaše aktuální struktura má formuláře obsahující dílčí dokument, z nichž každý klíč obsahuje další dílčí dokument s jedinou vlastností, status . Toto je obtížné procházet jako vaše forms element má libovolnou strukturu pro každý dokument, který vytvoříte. To znamená, že vzor sestoupí do status informace, které chcete porovnat změny pro každý dokument ve vaší sbírce.

Zde je to, co myslím cestou. Chcete-li získat stav v libovolném prvku, musíte provést následující

S druhým prvkem se neustále mění. Neexistuje žádný způsob na zástupný znak něco takového jako pojmenování je považováno za explicitní.

To může být považováno za snadný způsob implementace serializace dat z vašich formulářů ale vidím to flexibilnější alternativní. Co potřebujete, je struktura dokumentu, kterou můžete procházet ve standardním vzoru. To je vždy něco, co stojí za zvážení v designu. Vezměte následující:

{
    "_id" : "Tvq444454j",
    "name": "Jim",
    "forms": [
        {
             "name": "Jorney",
             "status":"closed"          
        },
        {
            "name": "Women",
            "status":"void"            
        },
        {
            "name": "Child",
            "status":"closed"           
        },
        {
            "name": "Farm",
            "status":"closed"            
        }  
    ]
}

Struktura dokumentu se tedy změní na forms prvek pole a místo toho, abychom umístili pole stavu pod klíč, který pojmenovává "pole formuláře", máme každý člen pole jako dílčí dokument obsahující "pole formuláře" name a status . Takže identifikátor i stav jsou stále spárovány dohromady, ale nyní jsou reprezentovány pouze jako dílčí dokument. Tím se především změní přístupová cesta k těmto klíčům, jako nyní pro obě název pole a jeho stav, který můžeme udělat

Co to znamená, že můžete dotazem najít názvy všech polí ve form nebo všechny status pole ve form , nebo dokonce všechny dokumenty s určitým name pole a určitý status . To je mnoho lepší, než co by se dalo udělat s původní strukturou.

Nyní ve vašem konkrétním případě chcete získat pouze dokumenty, kde jsou vše pole nejsou void . Nyní neexistuje způsob, jak to udělat v jediném dotazu, protože neexistuje žádný operátor, který by tímto způsobem porovnal všechny prvky v poli a zjistil, zda jsou stejné. Existují však dva přístupy, které můžete použít:

První a pravděpodobně ne tak efektivní je dotazování všech dokumenty, které obsahují prvek ve forms který má status "prázdného". S výsledným ID dokumentu můžete zadat další dotaz, který vrátí dokumenty, které ne mají zadaná ID.

db.forms.find({ "forms.status": "void" },{ _id: 1})

db.forms.find({ _id: $not: { $in: [<Object1>,<Object2>,<Object3>,... ] } })

Vzhledem k velikosti výsledku to nemusí být možné a obecně to není dobrý nápad jako operátor vyloučení $not v podstatě vynutí úplnou kontrolu kolekce, takže jste nemohli použít index.

Dalším přístupem je použití agregačního kanálu následovně:

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" }}
])

To samozřejmě vrátí _id pouze pro dokumenty, které se shodují, ale můžete zadat dotaz s $in a vrátit celé odpovídající dokumenty. To je lepší než operátor vyloučení používaný dříve a nyní můžeme použít index, abychom se vyhnuli prohledávání celé kolekce.

Jako konečný přístup a pro nejlepší z hlediska výkonu byste mohli dokument znovu změnit tak, že na nejvyšší úrovni budete udržovat "stav", zda je nějaké pole ve formulářích "void" nebo "zavřeno". Na nejvyšší úrovni by tedy hodnota byla uzavřena pouze v případě, že by byly všechny položky „zavřené“ a „neplatné“, pokud by bylo něco neplatné, a tak dále.

Ten poslední by znamenal další programovou změnu a všechny změny forms položky by musely aktualizovat i toto pole, aby si zachovaly „stav“. Je to však nejúčinnější způsob, jak najít dokumenty, které potřebujete, a může stát za zvážení.

UPRAVIT :

Kromě změny dokumentu na hlavní stav je nejrychlejší formulář dotazu na revidovanou strukturu ve skutečnosti:

db.forms.find({ "forms": { "$not": { "$elemMatch": { "status": "void" } } } })



  1. Mongoose se nevyplňuje (.populate()) na Production (Heroku), ale funguje na Local

  2. Jak zobrazit nahraný obrázek v back-endu Keystonejs

  3. Aktualizace dílčího dokumentu Mongoose, pokud existuje

  4. Groovy nemohl najít odpovídající konstruktor?