mongoose-fuzzy-searching ist ein einfaches und leichtes Plugin, das die Fuzzy-Suche in Dokumenten in MongoDB ermöglicht. Dieser Code basiert auf diesem Artikel.
Mit npm installieren
$ npm i mongoose-fuzzy-searching
oder mit Garn
$ yarn add mongoose-fuzzy-searching
Bevor Sie beginnen, sollten Sie alle Veraltungswarnungen korrekt behandeln, um Best Practices zu erhalten und Probleme zu vermeiden.
Damit das Plugin die Indizes erstellen kann, müssen Sie useCreateIndex
auf true setzen. Das folgende Beispiel zeigt, wie eine Verbindung mit der Datenbank hergestellt wird.
const options = {
useNewUrlParser : true ,
useUnifiedTopology : true ,
useFindAndModify : false ,
useCreateIndex : true ,
} ;
mongoose . Promise = global . Promise ;
return mongoose . connect ( URL , options ) ;
Im folgenden Beispiel haben wir eine User
Sammlung und möchten eine Fuzzy-Suche in firstName
und lastName
durchführen.
const { Schema } = require ( 'mongoose' ) ;
const mongoose_fuzzy_searching = require ( 'mongoose-fuzzy-searching' ) ;
const UserSchema = new Schema ( {
firstName : String ,
lastName : String ,
email : String ,
age : Number ,
} ) ;
UserSchema . plugin ( mongoose_fuzzy_searching , { fields : [ 'firstName' , 'lastName' ] } ) ;
const User = mongoose . model ( 'User' , UserSchema ) ;
module . exports = { User } ;
const user = new User ( { firstName : 'Joe' , lastName : 'Doe' , email : '[email protected]' , age : 30 } ) ;
try {
await user . save ( ) ; // mongodb: { ..., firstName_fuzzy: [String], lastName_fuzzy: [String] }
const users = await User . fuzzySearch ( 'jo' ) ;
console . log ( users ) ;
// each user object will not contain the fuzzy keys:
// Eg.
// {
// "firstName": "Joe",
// "lastName": "Doe",
// "email": "[email protected]",
// "age": 30,
// "confidenceScore": 34.3 ($text meta score)
// }
} catch ( e ) {
console . error ( e ) ;
}
Die Ergebnisse werden nach dem confidenceScore
Schlüssel sortiert. Sie können diese Option überschreiben.
try {
const users = await User . fuzzySearch ( 'jo' ) . sort ( { age : - 1 } ) . exec ( ) ;
console . log ( users ) ;
} catch ( e ) {
console . error ( e ) ;
}
Optionen können fields
und middlewares
enthalten.
Das Fields-Attribut ist obligatorisch und sollte entweder ein Array von Strings
oder ein Array von Objects
sein.
Wenn Sie die Standardoptionen für alle Ihre Felder verwenden möchten, können Sie sie einfach als Zeichenfolge übergeben.
const mongoose_fuzzy_searching = require ( 'mongoose-fuzzy-searching' ) ;
const UserSchema = new Schema ( {
firstName : String ,
lastName : String ,
email : String ,
} ) ;
UserSchema . plugin ( mongoose_fuzzy_searching , { fields : [ 'firstName' , 'lastName' ] } ) ;
Falls Sie eine der Standardoptionen für Ihre Argumente überschreiben möchten, können Sie sie als Objekt hinzufügen und alle gewünschten Werte überschreiben. Die folgende Tabelle enthält die erwarteten Schlüssel für dieses Objekt.
Schlüssel | Typ | Standard | Beschreibung |
---|---|---|---|
Name | Zeichenfolge | null | Name des Sammlungsschlüssels |
Mindestgröße | Ganze Zahl | 2 | N-Gramm Mindestgröße. Erfahren Sie mehr über N-Gramm |
Gewicht | Ganze Zahl | 1 | Gibt die Bedeutung des Feldes im Verhältnis zu den anderen indizierten Feldern im Hinblick auf die Textsuchbewertung an. Erfahren Sie mehr über Indexgewichte |
Nur Präfix | Boolescher Wert | FALSCH | Geben Sie nur ngrams vom Wortanfang zurück. (Es liefert genauere Ergebnisse) |
escapeSpecialCharacters | Boolescher Wert | WAHR | Entfernen Sie Sonderzeichen aus N-Grammen. |
Schlüssel | Array[String] | null | Wenn der Typ des Sammlungsattributs Object oder [Object] ist (siehe Beispiel), können Sie definieren, welche Attribute für die Fuzzy-Suche verwendet werden |
Beispiel:
const mongoose_fuzzy_searching = require ( 'mongoose-fuzzy-searching' ) ;
const UserSchema = new Schema ( {
firstName : String ,
lastName : String ,
email : String ,
content : {
en : String ,
de : String ,
it : String
}
text : [
{
title : String ,
description : String ,
language : String ,
} ,
] ,
} ) ;
UserSchema . plugin ( mongoose_fuzzy_searching , {
fields : [
{
name : 'firstName' ,
minSize : 2 ,
weight : 5 ,
} ,
{
name : 'lastName' ,
minSize : 3 ,
prefixOnly : true ,
} ,
{
name : 'email' ,
escapeSpecialCharacters : false ,
} ,
{
name : 'content' ,
keys : [ 'en' , 'de' , 'it' ] ,
} ,
{
name : 'text' ,
keys : [ 'title' , 'language' ] ,
} ,
] ,
} ) ;
Middlewares ist ein optionales Object
, das benutzerdefinierte pre
Middlewares enthalten kann. Dieses Plugin verwendet diese Middleware, um die Fuzzy-Elemente zu erstellen oder zu aktualisieren. Das heißt, wenn Sie pre
-Middlewares hinzufügen, werden diese nie aufgerufen, da das Plugin sie überschreibt. Um dieses Problem zu vermeiden, können Sie Ihre benutzerdefinierten Midlewares an das Plugin übergeben. Ihre Middleware wird zuerst aufgerufen. Die Middlewares, die Sie übergeben können, sind:
schema.pre("save", ...)
schema.pre("insertMany", ...)
schema.pre("update", ...)
schema.pre("updateOne", ...)
schema.pre("findOneAndUpdate", ...)
schema.pre("updateMany", ...)
Wenn Sie eine der oben genannten Middlewares hinzufügen möchten, können Sie diese direkt im Plugin hinzufügen.
const mongoose_fuzzy_searching = require ( 'mongoose-fuzzy-searching' ) ;
const UserSchema = new Schema ( {
firstName : String ,
lastName : String ,
} ) ;
UserSchema . plugin ( mongoose_fuzzy_searching , {
fields : [ 'firstName' ] ,
middlewares : {
preSave : function ( ) {
// do something before the object is saved
} ,
} ,
} ) ;
Middlewares können auch asynchrone Funktionen sein:
const mongoose_fuzzy_searching = require ( 'mongoose-fuzzy-searching' ) ;
const UserSchema = new Schema ( {
firstName : String ,
lastName : String ,
} ) ;
UserSchema . plugin ( mongoose_fuzzy_searching , {
fields : [ 'firstName' ] ,
middlewares : {
preUpdateOne : async function {
// do something before the object is updated (asynchronous)
}
}
} ) ;
Die Fuzzy-Suchabfrage kann entweder als static
Funktion oder als helper
verwendet werden, mit der Sie mehrere Abfragen miteinander verketten können. Der Funktionsname lautet in beiden Fällen Surprise, Surprise, fuzzySearch
.
Die Instanzmethode kann bis zu drei Parameter akzeptieren. Die erste ist die Abfrage, die entweder ein String
oder ein Object
sein kann. Dieser Parameter ist erforderlich . Der zweite Parameter kann entweder ein Object
sein, das zusätzliche Abfragen enthält (z. B. age: { $gt: 18 }
), oder eine Callback-Funktion. Wenn der zweite Parameter die Abfragen sind, ist der dritte Parameter die Rückruffunktion. Wenn Sie keine Rückruffunktion festlegen, werden die Ergebnisse in einem Promise zurückgegeben.
Die folgende Tabelle enthält die erwarteten Schlüssel für den ersten Parameter (wenn es sich um ein Objekt handelt).
Schlüssel | Typ | taub | Beschreibung |
---|---|---|---|
Abfrage | Zeichenfolge | null | Zu durchsuchende Zeichenfolge |
Mindestgröße | Ganze Zahl | 2 | N-Gramm Mindestgröße. |
Nur Präfix | Boolescher Wert | FALSCH | Geben Sie nur ngrams vom Wortanfang zurück. (Es liefert genauere Ergebnisse) das Präfix |
genau | Boolescher Wert | FALSCH | Übereinstimmungen mit einer Wortgruppe und nicht mit einzelnen Begriffen |
Beispiel:
/* With string that returns a Promise */
User . fuzzySearch ( 'jo' ) . then ( console . log ) . catch ( console . error ) ;
/* With additional options that returns a Promise */
User . fuzzySearch ( { query : 'jo' , prefixOnly : true , minSize : 4 } )
. then ( console . log )
. catch ( console . error ) ;
/* With additional queries that returns a Promise */
User . fuzzySearch ( 'jo' , { age : { $gt : 18 } } )
. then ( console . log )
. catch ( console . error ) ;
/* With string and a callback */
User . fuzzySearch ( 'jo' , ( err , doc ) => {
if ( err ) {
console . error ( err ) ;
} else {
console . log ( doc ) ;
}
} ) ;
/* With additional queries and callback */
User . fuzzySearch ( 'jo' , { age : { $gt : 18 } } , ( err , doc ) => {
if ( err ) {
console . error ( err ) ;
} else {
console . log ( doc ) ;
}
} ) ;
Sie können die Abfrage auch als Hilfsfunktion verwenden, die Instanzmethoden ähnelt, jedoch für Mungo-Abfragen. Mit Abfragehilfsmethoden können Sie die verkettbare Abfrage-Builder-API von mongoose erweitern.
Der Abfragehelfer kann bis zu zwei Parameter akzeptieren. Die erste ist die Abfrage, die entweder ein String
oder ein Object
sein kann. Dieser Parameter ist erforderlich . Der zweite Parameter kann ein Object
sein, das zusätzliche Abfragen enthält (z. B. age: { $gt: 18 }
), was optional ist. Dieser Helfer akzeptiert keine Rückruffunktion. Wenn Sie eine Funktion übergeben, wird ein Fehler ausgegeben. Mehr über Abfragehelfer.
Beispiel:
const user = await User . find ( { age : { $gte : 30 } } )
. fuzzySearch ( 'jo' )
. exec ( ) ;
Das Plugin erstellt Indizes für die ausgewählten Felder. Im folgenden Beispiel lauten die neuen Indizes firstName_fuzzy
und lastName_fuzzy
. Außerdem verfügt jedes Dokument über die Felder firstName_fuzzy
[String] und lastName_fuzzy
[String]. Diese Arrays enthalten die Anagramme für die ausgewählten Felder.
const mongoose_fuzzy_searching = require ( 'mongoose-fuzzy-searching' ) ;
const UserSchema = new Schema ( {
firstName : String ,
lastName : String ,
email : String ,
age : Number ,
} ) ;
UserSchema . plugin ( mongoose_fuzzy_searching , { fields : [ 'firstName' , 'lastName' ] } ) ;
Mit anderen Worten: Dieses Plugin erstellt Anagramme, wenn Sie ein Dokument erstellen oder aktualisieren. Alle bereits vorhandenen Dokumente enthalten diese Fuzzy-Arrays nicht, sodass die fuzzySearch
Funktion sie nicht finden kann.
Um Anagramme für bereits vorhandene Dokumente zu erstellen, sollten Sie jedes Dokument aktualisieren. Im folgenden Beispiel wird das Attribut firstName
für jedes Dokument in der Sammlung User
aktualisiert.
const cursor = Model . find ( ) . cursor ( ) ;
cursor . next ( function ( error , doc ) {
const obj = attrs . reduce ( ( acc , attr ) => ( { ... acc , [ attr ] : doc [ attr ] } ) , { } ) ;
return Model . findByIdAndUpdate ( doc . _id , obj ) ;
} ) ;
Im vorherigen Beispiel haben wir firstName
und lastName
als Fuzzy-Attribute festgelegt. Wenn Sie den firstName
aus den Fuzzy-Feldern entfernen, wird das Array firstName_fuzzy
nicht von der Sammlung entfernt. Wenn Sie das Array in jedem Dokument entfernen möchten, müssen Sie diesen Wert deaktivieren.
const cursor = Model . find ( ) . cursor ( ) ;
cursor . next ( function ( error , doc ) {
const $unset = attrs . reduce ( ( acc , attr ) => ( { ... acc , [ ` ${ attr } _fuzzy` ] : 1 } ) , { } ) ;
return Model . findByIdAndUpdate ( data . _id , { $unset } , { new : true , strict : false } ) ;
} ) ;
Wir verwenden Jest für alle unsere Unit- und Integrationstests.
$ npm test
Hinweis: Dadurch werden alle Suiten seriell ausgeführt, um mehrere gleichzeitige Verbindungen auf der Datenbank zu vermeiden.
Dadurch werden die Tests mithilfe einer Speicherdatenbank ausgeführt. Wenn Sie die Tests aus irgendeinem Grund über eine tatsächliche Verbindung auf einer Mongo-Instanz ausführen möchten, fügen Sie die Umgebungsvariable MONGO_DB
hinzu:
$ docker run --name mongo_fuzzy_test -p 27017:27017 -d mongo
$ MONGO_DB=true npm test
$ npm run test:unit
$ npm run test:integration
MIT-Lizenz
Copyright (c) 2019 Vassilis Pallas
Hiermit wird jeder Person, die eine Kopie dieser Software und der zugehörigen Dokumentationsdateien (die „Software“) erhält, kostenlos die Erlaubnis erteilt, mit der Software ohne Einschränkung zu handeln, einschließlich und ohne Einschränkung der Rechte zur Nutzung, zum Kopieren, Ändern und Zusammenführen , Kopien der Software zu veröffentlichen, zu verteilen, unterzulizenzieren und/oder zu verkaufen und Personen, denen die Software zur Verfügung gestellt wird, dies zu gestatten, vorbehaltlich der folgenden Bedingungen:
Der obige Urheberrechtshinweis und dieser Genehmigungshinweis müssen in allen Kopien oder wesentlichen Teilen der Software enthalten sein.
DIE SOFTWARE WIRD „WIE BESEHEN“ ZUR VERFÜGUNG GESTELLT, OHNE JEGLICHE AUSDRÜCKLICHE ODER STILLSCHWEIGENDE GEWÄHRLEISTUNG, EINSCHLIESSLICH, ABER NICHT BESCHRÄNKT AUF DIE GEWÄHRLEISTUNG DER MARKTGÄNGIGKEIT, EIGNUNG FÜR EINEN BESTIMMTEN ZWECK UND NICHTVERLETZUNG. IN KEINEM FALL SIND DIE AUTOREN ODER COPYRIGHT-INHABER HAFTBAR FÜR JEGLICHE ANSPRÜCHE, SCHÄDEN ODER ANDERE HAFTUNG, WEDER AUS EINER VERTRAGLICHEN HANDLUNG, AUS HANDLUNG ODER ANDERWEITIG, DIE SICH AUS, AUS ODER IN VERBINDUNG MIT DER SOFTWARE ODER DER NUTZUNG ODER ANDEREN HANDELN IN DER SOFTWARE ERGEBEN SOFTWARE.