sql >> Databasteknik >  >> NoSQL >> MongoDB

MongoDB frågar optimering

Det du vill ha är ett "facetterad sökning"-resultat där du håller statistiken om de matchade termerna i den aktuella resultatuppsättningen. Sedan, även om det finns produkter som "tycks" göra allt arbete i ett enda svar, måste du tänka på att de flesta generiska lagringsmotorer kommer att behöva flera operationer.

Med MongoDB kan du använda två frågor för att få själva resultaten och en annan för att få aspektinformationen. Detta skulle ge liknande resultat som de facetterade resultaten som är tillgängliga från dedikerade sökmotorprodukter som Solr eller ElasticSearch.

Men för att göra detta effektivt vill du inkludera detta i ditt dokument på ett sätt som det kan användas effektivt. En mycket effektiv form för vad du vill ha är att använda en rad tokeniserade data:

 {
     "otherData": "something",
     "facets": [
         "country:UK",
         "city:London-UK",
         "genre:Student"
     ]
 }

Så "faktetter" är ett enda fält i ditt dokument och inte på flera platser. Detta gör det mycket enkelt att indexera och fråga. Sedan kan du effektivt aggregera över dina resultat och få summan för varje aspekt:

User.aggregate(
    [
        { "$unwind": "$facets" },
        { "$group": {
            "_id": "$facets",
            "count": { "$sum": 1 }
        }}
    ],
    function(err,results) {

    }
);

Eller mer idealiskt med några kriterier i $match :

User.aggregate(
    [
        { "$match": { "facets": { "$in": ["genre:student"] } } },
        { "$unwind": "$facets" },
        { "$group": {
            "_id": "$facets",
            "count": { "$sum": 1 }
        }}
    ],
    function(err,results) {

    }
);

I slutändan ger ett svar som:

{ "_id": "country:FR", "count": 50 },
{ "_id": "country:UK", "count": 300 },
{ "_id": "city:London-UK", "count": 150 },
{ "_id": "genre:Student": "count": 500 }

En sådan struktur är lätt att passera och inspektera för saker som det diskreta "landet" och "staden" som hör till ett "land" eftersom dessa data bara separeras konsekvent med ett bindestreck "-".

Att försöka blanda ihop dokument inom arrayer är en dålig idé. Det finns en BSON-storleksgräns på 16 MB som också ska respekteras, från vilken sammanblandningsresultat (speciellt om du försöker behålla dokumentinnehållet) med största säkerhet kommer att överskridas i svaret.

För något så enkelt som att sedan få det "övergripande antalet" resultat från en sådan fråga, summera bara elementen i en viss aspekttyp. Eller skicka bara samma frågeargument till en .count() operation:

User.count({ "facets": { "$in": ["genre:Student"] } },function(err,count) {

});

Som sagt här, särskilt när du implementerar "personsökning" av resultat, är rollerna för att få "Resultaträkning", "Faceträkningar" och den faktiska "resultatsidan" alla delegerade till "separata" frågor till servern.

Det är inget fel med att skicka in var och en av dessa frågor till servern parallellt och sedan kombinera en struktur för att mata in din mall eller applikation som ser ungefär ut som det facetterade sökresultatet från en av sökmotorprodukterna som erbjuder den här typen av svar.

Avslutande

Så lägg något i ditt dokument för att markera aspekterna på ett enda ställe. En rad tokeniserade strängar fungerar bra för detta ändamål. Det fungerar också bra med frågeformulär som $in och $all för antingen "eller" eller "och"-villkor på kombinationer av facettval.

Försök inte att blanda resultat eller bygga tillägg bara för att matcha någon upplevd hierarkisk struktur, utan tvärsöver istället de mottagna resultaten och använd enkla mönster i tokens. Det är väldigt enkelt att

Kör sökfrågor för innehållet som separata frågor till antingen aspekter eller övergripande räkningar. Att försöka pressa allt innehåll i arrayer och sedan begränsa ut bara för att få räkningar är inte meningsfullt. Detsamma skulle gälla för en RDBMS-lösning för att göra samma sak, där sökningsresultatet räknas och den aktuella sidan är separata frågeoperationer.

Det finns mer information skriven på MongoDB-bloggen om Faceted Search med MongoDB som också förklarar några andra alternativ. Det finns också artiklar om integration med externa söklösningar med mongoconnector eller andra metoder.




  1. Använda Redis för köer för flera Laravel-applikationer på en enda server

  2. Finns det något sätt att flushall på ett kluster så att alla nycklar från master och slavar raderas från db

  3. Kontrollera om ett index finns i mongodb

  4. Uppdatera kapslade arrayobjekt baserat på en egenskap i MongoDB