To, czego potrzebujesz, to wynik „wyszukiwania aspektowego”, w którym przechowujesz statystyki dotyczące dopasowanych terminów w bieżącym zestawie wyników. Następnie, chociaż istnieją produkty, które „wydaje się” wykonywać całą pracę w jednej odpowiedzi, należy wziąć pod uwagę, że większość ogólnych silników pamięci masowej będzie wymagała wielu operacji.
Dzięki MongoDB możesz użyć dwóch zapytań, aby uzyskać same wyniki, a drugiego, aby uzyskać informacje o aspekcie. Dałoby to podobne wyniki do wyników aspektowych dostępnych z dedykowanych wyszukiwarek, takich jak Solr lub ElasticSearch.
Ale aby zrobić to skutecznie, chcesz uwzględnić to w swoim dokumencie w taki sposób, aby można było z niego efektywnie korzystać. Bardzo skuteczną formą tego, czego chcesz, jest użycie tablicy tokenizowanych danych:
{
"otherData": "something",
"facets": [
"country:UK",
"city:London-UK",
"genre:Student"
]
}
Tak więc „fakty” to jedno pole w twoim dokumencie, a nie w wielu lokalizacjach. Dzięki temu indeksowanie i zapytania są bardzo łatwe. Następnie możesz skutecznie agregować wyniki i uzyskać sumy dla każdego aspektu:
User.aggregate(
[
{ "$unwind": "$facets" },
{ "$group": {
"_id": "$facets",
"count": { "$sum": 1 }
}}
],
function(err,results) {
}
);
Lub lepiej z pewnymi kryteriami w $match
:
User.aggregate(
[
{ "$match": { "facets": { "$in": ["genre:student"] } } },
{ "$unwind": "$facets" },
{ "$group": {
"_id": "$facets",
"count": { "$sum": 1 }
}}
],
function(err,results) {
}
);
Ostatecznie udzielając odpowiedzi, takiej jak:
{ "_id": "country:FR", "count": 50 },
{ "_id": "country:UK", "count": 300 },
{ "_id": "city:London-UK", "count": 150 },
{ "_id": "genre:Student": "count": 500 }
Taka struktura jest łatwa do przemierzenia i sprawdzenia pod kątem takich rzeczy, jak dyskretny „kraj” i „miasto” należące do „kraju”, ponieważ dane te są po prostu konsekwentnie oddzielone myślnikiem „-”.
Próba łączenia dokumentów w tablice to zły pomysł. Należy również przestrzegać limitu rozmiaru BSON wynoszącego 16 MB, z którego wynika, że połączenie (zwłaszcza jeśli próbujesz zachować treść dokumentu) z pewnością zostanie przekroczone w odpowiedzi.
W przypadku czegoś tak prostego, jak uzyskanie „ogólnej liczby” wyników z takiego zapytania, wystarczy zsumować elementy określonego typu aspektu. Lub po prostu wyślij te same argumenty zapytania do .count()
operacja:
User.count({ "facets": { "$in": ["genre:Student"] } },function(err,count) {
});
Jak wspomniano tutaj, szczególnie podczas implementowania „stronicowania” wyników, role pobierania „Liczba wyników”, „Liczba aspektów” i rzeczywista „Strona wyników” są delegowane do „oddzielenia” zapytań do serwera.
Nie ma nic złego w równoległym przesyłaniu każdego z tych zapytań do serwera, a następnie łączeniu struktury, która będzie przesyłana do szablonu lub aplikacji, która wygląda bardzo podobnie do wyników wyszukiwania aspektowego z jednej z wyszukiwarek, które oferują tego rodzaju odpowiedzi.
Podsumowanie
Więc umieść coś w swoim dokumencie, aby zaznaczyć fasety w jednym miejscu. W tym celu dobrze sprawdza się tablica tokenizowanych ciągów. Działa również dobrze z formularzami zapytań, takimi jak $in
i $all
dla warunków „lub” lub „i” w kombinacjach wyboru aspektów.
Nie próbuj łączyć wyników lub zagnieżdżać dodatków tylko po to, aby dopasować jakąś postrzeganą strukturę hierarchiczną, ale raczej przeszukuj otrzymane wyniki i używaj prostych wzorców w tokenach. To bardzo proste
Uruchom kwerendy stronicowane dotyczące zawartości jako oddzielne kwerendy do aspektów lub ogólnej liczby. Próba wypychania całej zawartości do tablic, a następnie ograniczania się tylko po to, aby uzyskać liczbę, nie ma sensu. To samo dotyczy rozwiązania RDBMS, które robi to samo, gdzie zliczanie wyników stronicowania i bieżąca strona są oddzielnymi operacjami zapytania.
Więcej informacji na temat wyszukiwania aspektowego z MongoDB znajduje się na blogu MongoDB, które wyjaśniają również inne opcje. Istnieją również artykuły na temat integracji z zewnętrznymi rozwiązaniami wyszukiwania przy użyciu mongoconnectora lub innych podejść.