MongoDB
 sql >> Baza danych >  >> NoSQL >> MongoDB

Warunek dopasowania składowych tablicy sumarycznej liczby elementów

Błąd jest spowodowany tym, że nie jest to już tablica po $unwind i dlatego nie jest już prawidłowym argumentem $size .

Wygląda na to, że próbujesz „scalić” kilka istniejących odpowiedzi, nie rozumiejąc, co robią. To, czego naprawdę chcesz tutaj, to $filter i $size

db.collection.aggregate([
  { "$project": {
    "total": {
      "$size": {
        "$filter": {
          "input": "$Array",
          "cond": { "$eq": [ "$$this.field1", "a" ] }
        }
      }
    }
  }}
])

Lub „wymyśl na nowo koło” za pomocą $reduce :

db.collection.aggregate([
  { "$project": {
    "total": {
      "$reduce": {
        "input": "$Array",
        "initialValue": 0,
        "in": {
          "$sum": [
            "$$value", 
            { "$cond": [{ "$eq": [ "$$this.field1", "a" ] }, 1, 0] }
        }
      }
    }
  }}
])

Lub za to, co próbowałeś zrobić z $unwind , właściwie $group ponownie, aby „policzyć”, ile było dopasowań:

db.collection.aggregate([
  { "$unwind": "$Array" },
  { "$match": { "Array.field1": "a" } },
  { "$group": {
    "_id": "$_id",
    "total": { "$sum": 1 }
  }}
])

Pierwsze dwie formy są "optymalne" dla nowoczesnych środowisk MongoDB. Ostateczny formularz z $unwind i $group jest "starszą" konstrukcją, która tak naprawdę nie była potrzebna do tego typu operacji od MongoDB 2.6, chociaż z kilkoma nieco innymi operatorami.

W tych pierwszych dwóch po prostu porównujemy pole1 wartość każdego elementu tablicy, podczas gdy nadal jest to tablica. Oba $filter i $reduce to nowoczesne operatory zaprojektowane do pracy z istniejącą macierzą. To samo porównanie jest wykonywane na każdym z nich przy użyciu agregacji $eq operator, który zwraca wartość logiczną na podstawie tego, czy podane argumenty są „równe”, czy nie. W tym przypadku na każdym elemencie tablicy do oczekiwanej wartości "a" .

W przypadku $filter , tablica pozostaje nienaruszona, z wyjątkiem elementów, które nie spełniły podanego warunku w "cond" są usuwane z tablicy. Ponieważ nadal mamy „tablicę” jako dane wyjściowe, możemy użyć $rozmiar operator do pomiaru liczby elementów tablicy pozostałych po przetworzeniu warunku filtra.

$reduce z drugiej strony działa poprzez elementy tablicy i dostarcza wyrażenie nad każdym elementem oraz przechowywaną wartość "akumulatora", którą zainicjalizowaliśmy za pomocą "initialValue" . W tym przypadku ten sam $eq test jest stosowany w ramach $cond operator. To jest „trójkąt” lub if/then/else operator warunkowy, który umożliwia testowanemu wyrażeniu zwracającemu wartość logiczną zwrócenie then wartość, gdy prawda lub inne wartość, gdy false .

W tym wyrażeniu zwracamy 1 lub 0 odpowiednio i podaj ogólny wynik dodania tej zwróconej wartości i bieżącej "akumulatora" "$$value" z $sum operatora, aby dodać je razem.

Ostateczna forma użyta $unwind na tablicy. To, co w rzeczywistości robi, to dekonstruuje elementy członkowskie tablicy, aby utworzyć „nowy dokument” dla każdego elementu członkowskiego tablicy i powiązanych z nim pól nadrzędnych w oryginalnym dokumencie. To skutecznie „kopiuje” główny dokument dla każdego członka tablicy.

Gdy $unwind zmieniono strukturę dokumentów na bardziej „płaską”. Dlatego możesz wykonać kolejne $match etap potoku, aby usunąć niedopasowane dokumenty.

To prowadzi nas do $group który jest stosowany do "sprowadzenia" wszystkich informacji związanych ze wspólnym kluczem. W tym przypadku jest to _id pole oryginalnego dokumentu, które oczywiście zostało skopiowane do każdego dokumentu wyprodukowanego przez $odpręż . Wracając do tego „klucza wspólnego” jako pojedynczego dokumentu, możemy „policzyć” pozostałe „dokumenty” wyodrębnione z tablicy za pomocą $sum akumulator.

Jeśli chcielibyśmy odzyskać pozostałą „tablicę”, możesz $push i odbuduj tablicę tylko z pozostałymi członkami:

  { "$group": {
    "_id": "$_id",
    "Array": { "$push": "$Array" },
    "total": { "$sum": 1 }
  }}

Ale oczywiście zamiast używać $size na innym etapie potoku możemy po prostu nadal „liczyć”, tak jak to zrobiliśmy już z $ suma




  1. Redis
  2.   
  3. MongoDB
  4.   
  5. Memcached
  6.   
  7. HBase
  8.   
  9. CouchDB
  1. Błąd MongoDB:nie można użyć wielokrotnego zapisu z limitem=0

  2. 5 sposobów na wybranie wierszy o maksymalnej wartości dla ich grupy w SQL

  3. Jak uzyskać wszystkie pasujące elementy z tablicy obiektów w MongoDB?

  4. Klonowanie instancji MongoDB lub zestawu replik

  5. Meteor pochłania ogromną liczbę połączeń Mongo