sql >> Database teknologi >  >> NoSQL >> MongoDB

Mongoose - Søg efter tekst i tre felter baseret på score eller vægt

Et "tekstindeks" og søgning er faktisk sandsynligvis den bedste mulighed her, så længe du søger efter hele ord.

Tilføjelse af et tekstindeks til din skemadefinition er ret simpelt:

BookSchema.index(
    {
         "name": "text",
         "description": "text",
         "body": "text"
    },
    {
        "weights": {
            "name": 5,
            "description": 2
        }
    }
)

Dette giver dig mulighed for at udføre simple søgninger med "indstil" vægtning til felterne:

Book.find({ "$text": { "$search": "Holiday School Year" } })
    .select({ "score": { "$meta": "textScore" } })
    .sort({ "score": { "$meta": "textScore" } })
    .exec(function(err,result) {

    }
);

Hvor hvert udtryk matchet vil blive betragtet i forhold til det felt, det blev fundet i, som giver størst vægt og antallet af forekomster.

Tildeling af vægte er knyttet til "indekset", så definitionen udføres én gang og kan ikke ændres. En anden begrænsning er, at ved "tekstsøgning" ikke ser på "delvise" ord. For eksempel matcher "ci" ikke "By" eller "Borger", og for sådan noget skal du i stedet bruge et regulært udtryk.

Hvis du havde brug for mere fleksibilitet end det eller generelt skal være i stand til dynamisk at ændre vægtningen af ​​resultater, så har du brug for noget som aggregeringsrammen eller mapReduce.

Aggregeringsrammen kan dog ikke udføre et "logisk" match operation (den kan filtrere gennem $match operator, men ikke et "logisk" match ) af et "regulært udtryk" til dine udtryk. Du kan dog arbejde med enkelte ord og "nøjagtige" match, hvis dette passer.

Book.aggregate(
    [
        { "$match": {
            "$or": [
                { "name": /Holiday/ },
                { "description": /Holiday/ },
                { "body": /Holiday/ }
            ]
        }},
        { "$project": {
            "name": 1,
            "description": 1,
            "body": 1,
            "score": {
                "$add": [
                    { "$cond": [{ "$eq": [ "$name", "Holiday" ] },5,0 ] },
                    { "$cond": [{ "$eq": [ "$description", "Holiday" ] },2,0 ] },
                    { "$cond": [{ "$eq": [ "$body", "Holiday" ] },1,0 ] }
                ]
            }
        }},
        { "$sort": { "score": -1 } }
    ],
    function(err,results) {

    }
)

Som en aggregeringspipeline bruger en datastruktur til at forespørge, hvor du kan ændre parametrene for vægt på hver udstrækning til det, du har brug for lige nu.

MapReduce deler et lignende princip, hvor du kan inkludere en beregnet "score" i en del af den primære nøgle, der udsendes som det ledende element. MapReduce sorterer naturligvis alle input, der udsendes af denne tast, som en optimering for fodring til en reducerfunktion. Du kan dog ikke yderligere sortere eller "begrænse" et sådant resultat.

Det er generelt dine muligheder for at se på og beslutte, hvad der passer bedst til din sag.




  1. Mongodb monogorestore rodmappe skal være et dump af en enkelt database

  2. Sådan finder du forespørgsler, der ikke bruger indekser eller er langsom i mongodb

  3. $push og $set i samme MongoDB-opdatering

  4. Express node.js-controlleren venter ikke på datamanipulation og returnerer gamle data