MongoDB
 sql >> Datenbank >  >> NoSQL >> MongoDB

Mongoose - Suchen Sie nach Text in drei Feldern basierend auf Punktzahl oder Gewichtung

Ein "Textindex" und Suche ist in der Tat wahrscheinlich die beste Option, solange Sie nach ganzen Wörtern suchen.

Das Hinzufügen eines Textindex zu Ihrer Schemadefinition ist ganz einfach:

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

Damit können Sie einfache Suchen mit "festgelegter" Gewichtung zu den Feldern durchführen:

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

    }
);

Wo jeder gefundene Begriff mit dem Feld verglichen wird, in dem er gefunden wurde, was die größte Gewichtung und die Anzahl der Vorkommen ergibt.

Die Zuordnung der Gewichte wird an den „Index“ angehängt, die Definition erfolgt also einmalig und kann nicht geändert werden. Eine weitere Einschränkung besteht darin, dass bei der „Textsuche“ nicht nach „Teilwörtern“ gesucht wird. Zum Beispiel passt „ci“ nicht zu „Stadt“ oder „Bürger“, und für so etwas bräuchten Sie stattdessen einen regulären Ausdruck.

Wenn Sie mehr Flexibilität benötigen oder die Gewichtung von Ergebnissen generell dynamisch ändern können müssen, benötigen Sie so etwas wie das Aggregation Framework oder mapReduce.

Das Aggregations-Framework kann jedoch keine "logische" Übereinstimmung Operation (kann durch den $match filtern -Operator, aber keine "logische" Übereinstimmung ) eines "regulären Ausdrucks" mit Ihren Begriffen. Sie können jedoch mit einzelnen Wörtern und "exakten" Übereinstimmungen arbeiten, wenn dies passt.

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) {

    }
)

Da eine Aggregationspipeline eine Datenstruktur verwendet, um abzufragen, wo Sie die Parameter für die Gewichtung bei jeder Ausführung auf das ändern können, was Sie gerade benötigen.

MapReduce hat ein ähnliches Prinzip, bei dem Sie eine berechnete "Punktzahl" in einen Teil des Primärschlüssels aufnehmen können, der als führendes Element ausgegeben wird. MapReduce sortiert natürlich alle Eingaben, die von dieser Taste ausgegeben werden, als Optimierung für die Zuführung zu einer Reduzierungsfunktion. Allerdings können Sie ein solches Ergebnis nicht weiter sortieren oder "eingrenzen".

Dies sind im Allgemeinen Ihre Optionen, die Sie prüfen und entscheiden können, welche am besten zu Ihrem Fall passt.