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

Rama agregacji mongodb pasuje do zagnieżdżonych dokumentów

Zapytanie tej struktury o pożądane wyniki nie jest możliwe bez znajomości wszystkich możliwych forms nazwy wcześniej i używając ich w zapytaniu. W każdym razie byłoby to bardzo bałaganiarskie. To powiedziawszy, czytaj dalej, gdy wyjaśnię, jak to zrobić.

Istnieje problem ze strukturą tych dokumentów, który uniemożliwia wykonanie rozsądnej analizy zapytań. W obecnej sytuacji musiałbyś znać wszystkie możliwe pola nazw formularzy, aby cokolwiek odfiltrować.

Twoja obecna struktura ma formularze zawierające dokument podrzędny, z których każdy klucz zawiera inny dokument podrzędny z jedną właściwością, status . Jest to trudne do przejścia, ponieważ Twoje forms element ma dowolną strukturę dla każdego tworzonego dokumentu. Oznacza to wzorzec schodzenia do status informacje, które chcesz porównać zmiany dla każdego dokumentu w Twojej kolekcji.

Oto, co rozumiem przez ścieżkę. Aby uzyskać status w dowolnym elemencie, musisz wykonać następujące czynności

Z drugim elementem zmieniającym się cały czas. Nie ma nie ma mowy do wieloznacznika coś takiego, ponieważ nazewnictwo jest uważane za jednoznaczne.

Może to być uważane za łatwy sposób na zaimplementowanie serializacji danych z Twoich formularzy ale widzę bardziej elastyczny alternatywny. Potrzebujesz struktury dokumentu, którą możesz przemierzać według standardowego wzorca. To jest zawsze coś, co warto wziąć pod uwagę w projektowaniu. Wykonaj następujące czynności:

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

Tak więc struktura dokumentu została zmieniona, aby forms element Array, a zamiast umieszczać pole statusu pod kluczem, który nazywa "pole formularza", każdy element tablicy jest dokumentem podrzędnym zawierającym "pole formularza" name i status . Tak więc zarówno identyfikator, jak i status są nadal sparowane, ale teraz są reprezentowane jako dokument podrzędny. To co najważniejsze zmienia ścieżkę dostępu do tych kluczy, tak jak teraz w przypadku obu nazwę pola i jego status, który możemy wykonać

Co to? oznacza to, że możesz wykonać zapytanie, aby znaleźć nazwy wszystkich pól w form lub cały status pola w form , a nawet wszystkie dokumenty z określoną name pole i określony status . To dużo lepsze niż to, co można zrobić z oryginalną strukturą.

Teraz w swoim konkretnym przypadku chcesz uzyskać tylko dokumenty, w których wszystkie pola nie są void . Teraz nie ma możliwości wykonania tego w pojedynczym zapytaniu, ponieważ nie ma operatora, który porównuje w ten sposób wszystkie elementy tablicy i sprawdza, czy są takie same. Można jednak zastosować dwa podejścia:

Pierwszym i prawdopodobnie nie tak wydajnym jest zapytanie o wszystkie dokumenty zawierające element w forms który ma status "pustki". Z otrzymanymi identyfikatorami dokumentu możesz wydać kolejne zapytanie, które zwróci dokumenty, które nie mieć podane identyfikatory.

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

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

Biorąc pod uwagę rozmiar wyniku, może to nie być możliwe i generalnie nie jest dobrym pomysłem, ponieważ operator wykluczenia $not zasadniczo wymusza pełne skanowanie kolekcji, więc nie można było użyć indeksu.

Innym podejściem jest użycie potoku agregacji w następujący sposób:

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

Oczywiście zwróci to tylko _id dla pasujących dokumentów, ale możesz wydać zapytanie za pomocą $in i zwrócić całe pasujące dokumenty. Jest to lepsze niż wcześniej używany operator wykluczenia, a teraz możemy użyć indeksu, aby uniknąć pełnego skanowania kolekcji.

Jako ostateczne podejście i dla najlepszych Biorąc pod uwagę wydajność, można ponownie zmienić dokument, aby na najwyższym poziomie zachować „status” dowolnego pola w formularzach jako „nieważny” lub „zamknięty”. Tak więc na najwyższym poziomie wartość byłaby zamknięta tylko wtedy, gdy wszystkie elementy byłyby „zamknięte”, a „nieważne”, gdyby coś było nieważne i tak dalej.

Ta ostatnia oznaczałaby dalszą zmianę programistyczną i wszystkie zmiany w forms pozycje musiałyby również zaktualizować to pole, aby zachować „status”. Jest to jednak najskuteczniejszy sposób znajdowania potrzebnych dokumentów i może być warty rozważenia.

EDYTUJ :

Oprócz zmiany dokumentu na status główny, najszybszy formularz zapytania w zmienionej strukturze to w rzeczywistości:

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



  1. Redis
  2.   
  3. MongoDB
  4.   
  5. Memcached
  6.   
  7. HBase
  8.   
  9. CouchDB
  1. Znajdź minimalną i maksymalną wartość z tablicy w mongodb

  2. Błąd:nie można zainicjować klienta | mongo-connect express-sesja

  3. mongodb aktualizuje ostatni element tablicy

  4. Jak przesyłać powiadomienia push za pomocą angular.js?

  5. Projekt z dopasowaniem łącznie nie działa w mongodb