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

Problémy s agregačním rámcem SailsJS &MongoDB s vlastními dotazy

Váš první dotaz byl na správné cestě, kdy jste použili nesprávný operátor potrubí.

Artist.native(function(err,collection) {

    collection.aggregate(
        [
            { "$project": {
                "_id": 1,
                "name": 1,
                "total": { "$size": "$dubs" }
            }}
        ],
        function(err,result) {
          if (err) return res.serverError(err);
          console.log(result);
        }
})

Samozřejmě $size Operátor tam vyžaduje, abyste potřebovali verzi MongoDB 2.6 nebo vyšší, což byste už pravděpodobně měli udělat, ale stále můžete udělat to samé bez operátoru pro měření délky pole:

Artist.native(function(err,collection) {

    collection.aggregate(
        [
            { "$project": {
                "_id": 1,
                "name": 1,
                "dubs": {
                    "$cond": [
                       { "$eq": [ "$dubs", [] ] },
                       [0],
                       "$dubs"
                    ]
                }
            }},
            { "$unwind": "$dubs" },
            { "$group": {
                "_id": "$_id",
                "name": { "$first": "$name" },
                "total": { 
                    "$sum": {
                        "$cond": [
                            { "$eq": [ "$dubs", 0 ] },
                            0,
                            1
                        ]
                    }
                }
            }}
        ],
        function(err,result) {
          if (err) return res.serverError(err);
          console.log(result);
        }
})

To dělá totéž při počítání členů pole, ale místo toho byste museli $unwind prvky pole, aby je bylo možné spočítat. Takže to lze stále provést, ale není to tak efektivní.

Navíc musíte zvládnout případy, kdy je pole skutečně prázdné, ale přítomné, protože $unwind zpracovává prázdné pole [] . Pokud by neexistoval žádný obsah, pak by dokument obsahující takový prvek byl z výsledků odstraněn. Podobným způsobem byste museli použít $ ifNull nastavit pole, kde dokument neobsahoval ani prvek pro $unwind aby nedošlo k chybě.

Opravdu, pokud máte v úmyslu provádět tento druh dotazu pravidelně, měli byste v dokumentu udržovat pole "celkem" a ne se snažit jej nejprve vypočítat. Použijte $inc operátor spolu s operacemi, jako je $push a $pull k udržení aktuální délky pole.

To se sice trochu vzdaluje od obecné filozofie Waterline, ale již jste zavedli nativní agregační operace a není to zase tak složité, abyste si uvědomili, že díky používání nativních operací také v jiných oblastech získáváte lepší výkon.

Takže s dokumenty, jako jsou tyto:

{
  "dubs": [{},{},{}],
  "name": "The Doors",
  "createdAt": "2014-12-15T15:24:26.216Z",
  "updatedAt": "2014-12-15T15:24:26.216Z",
  "id": "548efd2a436c850000353f4f"
},
{
  "dubs": [],
  "name": "The Beatles",
  "createdAt": "2014-12-15T20:30:33.922Z",
  "updatedAt": "2014-12-15T20:30:33.922Z",
  "id": "548f44e90630d50000e2d61d"
}

V každém případě získáte přesně požadované výsledky:

{
    "_id" : ObjectId("5494b79d7e22da84d53c8760"),
    "name" : "The Doors",
    "total" : 3
},
{
    "_id" : ObjectId("5494b79d7e22da84d53c8761"),
    "name" : "The Beatles",
    "total" : 0
}



  1. Jedinečný index MongoDB na prvku pole napříč dokumenty (nikoli ve vnořených dokumentech)

  2. Rychlost MongoDB {aggregation $match} vs {find}

  3. Mongodb (v2.4.0) Agregát $match nefunguje s rozsahem dat

  4. Použijte createView s allowDiskUse