mongoose-fuzzy-searching adalah plugin sederhana dan ringan yang memungkinkan pencarian fuzzy dalam dokumen di MongoDB. Kode ini didasarkan pada artikel ini.
Instal menggunakan npm
$ npm i mongoose-fuzzy-searching
atau menggunakan benang
$ yarn add mongoose-fuzzy-searching
Sebelum memulai, untuk praktik terbaik dan menghindari masalah apa pun, tangani semua Peringatan Penghentian dengan benar.
Agar plugin dapat membuat indeks, Anda perlu menyetel useCreateIndex
ke true. Contoh di bawah ini menunjukkan cara terhubung dengan database.
const options = {
useNewUrlParser : true ,
useUnifiedTopology : true ,
useFindAndModify : false ,
useCreateIndex : true ,
} ;
mongoose . Promise = global . Promise ;
return mongoose . connect ( URL , options ) ;
Pada contoh di bawah ini, kami memiliki koleksi User
dan kami ingin membuat pencarian fuzzy di firstName
dan lastName
.
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 ) ;
}
Hasilnya diurutkan berdasarkan kunci confidenceScore
. Anda dapat mengesampingkan opsi ini.
try {
const users = await User . fuzzySearch ( 'jo' ) . sort ( { age : - 1 } ) . exec ( ) ;
console . log ( users ) ;
} catch ( e ) {
console . error ( e ) ;
}
Opsi dapat berisi fields
dan middlewares
.
Atribut bidang bersifat wajib dan harus berupa larik Strings
atau larik Objects
.
Jika Anda ingin menggunakan opsi default untuk semua bidang Anda, Anda cukup meneruskannya sebagai string.
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' ] } ) ;
Jika Anda ingin mengganti salah satu opsi default untuk argumen Anda, Anda bisa menambahkannya sebagai objek dan mengganti nilai apa pun yang Anda inginkan. Tabel di bawah berisi kunci yang diharapkan untuk objek ini.
kunci | jenis | bawaan | keterangan |
---|---|---|---|
nama | Rangkaian | batal | Nama kunci koleksi |
ukuran minimal | Bilangan bulat | 2 | Ukuran minimal N-gram. Pelajari lebih lanjut tentang N-gram |
berat | Bilangan bulat | 1 | Menunjukkan signifikansi bidang tersebut relatif terhadap bidang lain yang diindeks dalam hal skor penelusuran teks. Pelajari lebih lanjut tentang bobot indeks |
awalan saja | Boolean | PALSU | Hanya kembalikan ngram dari awal kata. (Ini memberikan hasil yang lebih tepat) |
escapeSpecialCharacters | Boolean | BENAR | Hapus karakter khusus dari N-gram. |
kunci | Array[String] | batal | Jika tipe atribut koleksi adalah Object atau [Object] (lihat contoh), Anda dapat menentukan atribut mana yang akan digunakan untuk pencarian fuzzy |
Contoh:
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 adalah Object
opsional yang dapat berisi pre
-middleware khusus. Plugin ini menggunakan middleware ini untuk membuat atau memperbarui elemen fuzzy. Artinya, jika Anda menambahkan pre
-middleware, mereka tidak akan pernah dipanggil karena plugin akan menimpanya. Untuk menghindari masalah itu, Anda dapat meneruskan midleware khusus Anda ke dalam plugin. Middleware Anda akan dipanggil terlebih dahulu . Middleware yang dapat Anda lewati adalah:
schema.pre("save", ...)
schema.pre("insertMany", ...)
schema.pre("update", ...)
schema.pre("updateOne", ...)
schema.pre("findOneAndUpdate", ...)
schema.pre("updateMany", ...)
Jika Anda ingin menambahkan salah satu middleware di atas, Anda dapat menambahkannya langsung di plugin.
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
} ,
} ,
} ) ;
Middleware juga dapat berupa fungsi asinkron:
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)
}
}
} ) ;
Kueri penelusuran fuzzy dapat digunakan sebagai fungsi static
, atau sebagai helper
, yang memungkinkan Anda merangkai beberapa kueri secara bersamaan. Nama fungsi dalam kedua kasus tersebut adalah kejutan, kejutan, fuzzySearch
.
Metode instance dapat menerima hingga tiga parameter. Yang pertama adalah kueri, yang bisa berupa String
atau Object
. Parameter ini diperlukan . Parameter kedua bisa berupa Object
yang berisi kueri tambahan (misalnya age: { $gt: 18 }
), atau fungsi panggilan balik. Jika parameter kedua adalah query, maka parameter ketiga adalah fungsi callback. Jika Anda tidak menyetel fungsi panggilan balik, hasilnya akan dikembalikan di dalam Janji.
Tabel di bawah ini berisi kunci yang diharapkan untuk parameter pertama (jika berupa objek)
kunci | jenis | tuli | keterangan |
---|---|---|---|
pertanyaan | Rangkaian | batal | String untuk mencari |
ukuran minimal | Bilangan bulat | 2 | Ukuran minimal N-gram. |
awalan saja | Boolean | PALSU | Hanya kembalikan ngram dari awal kata. (Ini memberikan hasil yang lebih tepat) awalan |
akurat | Boolean | PALSU | Cocok pada sebuah frase, bukan pada istilah individual |
Contoh:
/* 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 ) ;
}
} ) ;
Anda juga dapat menggunakan query is a helper function, yang mirip dengan metode instan tetapi untuk query luwak. Metode pembantu kueri memungkinkan Anda memperluas API pembuat kueri yang dapat dirantai milik luwak.
Pembantu kueri dapat menerima hingga dua parameter. Yang pertama adalah kueri, yang bisa berupa String
atau Object
. Parameter ini diperlukan . Parameter kedua dapat berupa Object
yang berisi kueri tambahan (misalnya age: { $gt: 18 }
), yang bersifat opsional. Pembantu ini tidak menerima fungsi panggilan balik. Jika Anda meneruskan suatu fungsi, itu akan menimbulkan kesalahan. Lebih lanjut tentang pembantu kueri.
Contoh:
const user = await User . find ( { age : { $gte : 30 } } )
. fuzzySearch ( 'jo' )
. exec ( ) ;
Plugin ini membuat indeks untuk bidang yang dipilih. Pada contoh di bawah ini, indeks barunya adalah firstName_fuzzy
dan lastName_fuzzy
. Selain itu, setiap dokumen akan memiliki kolom firstName_fuzzy
[String] dan lastName_fuzzy
[String]. Array ini akan berisi anagram untuk kolom yang dipilih.
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' ] } ) ;
Dengan kata lain, plugin ini membuat anagram saat Anda membuat atau memperbarui dokumen. Semua dokumen yang sudah ada sebelumnya tidak akan berisi array fuzzy ini, sehingga fungsi fuzzySearch
tidak akan dapat menemukannya.
Untuk membuat anagram untuk dokumen yang sudah ada, Anda harus memperbarui setiap dokumen. Contoh di bawah ini, memperbarui atribut firstName
ke setiap dokumen di koleksi User
.
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 ) ;
} ) ;
Pada contoh sebelumnya, kita menetapkan firstName
dan lastName
sebagai atribut fuzzy. Jika Anda menghapus firstName
dari bidang fuzzy, array firstName_fuzzy
tidak akan dihapus oleh koleksi. Jika Anda ingin menghapus array pada setiap dokumen, Anda harus menghapus nilai tersebut.
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 } ) ;
} ) ;
Kami menggunakan lelucon untuk semua pengujian unit dan integrasi kami.
$ npm test
Catatan: ini akan menjalankan semua suite secara serial untuk menghindari beberapa koneksi bersamaan di db.
Ini akan menjalankan pengujian menggunakan database memori. Jika karena alasan apa pun Anda ingin menjalankan pengujian menggunakan koneksi sebenarnya pada instance mongo, tambahkan variabel lingkungan MONGO_DB
:
$ docker run --name mongo_fuzzy_test -p 27017:27017 -d mongo
$ MONGO_DB=true npm test
$ npm run test:unit
$ npm run test:integration
Lisensi MIT
Hak Cipta (c) 2019 Vassilis Pallas
Izin dengan ini diberikan, secara gratis, kepada siapa pun yang memperoleh salinan perangkat lunak ini dan file dokumentasi terkait ("Perangkat Lunak"), untuk menggunakan Perangkat Lunak tanpa batasan, termasuk namun tidak terbatas pada hak untuk menggunakan, menyalin, memodifikasi, menggabungkan , mempublikasikan, mendistribusikan, mensublisensikan, dan/atau menjual salinan Perangkat Lunak, dan mengizinkan orang yang menerima Perangkat Lunak untuk melakukan hal tersebut, dengan tunduk pada ketentuan berikut:
Pemberitahuan hak cipta di atas dan pemberitahuan izin ini akan disertakan dalam semua salinan atau sebagian besar Perangkat Lunak.
PERANGKAT LUNAK INI DISEDIAKAN "APA ADANYA", TANPA JAMINAN APA PUN, TERSURAT MAUPUN TERSIRAT, TERMASUK NAMUN TIDAK TERBATAS PADA JAMINAN KELAYAKAN UNTUK DIPERDAGANGKAN, KESESUAIAN UNTUK TUJUAN TERTENTU, DAN TIDAK ADA PELANGGARAN. DALAM KEADAAN APA PUN PENULIS ATAU PEMEGANG HAK CIPTA TIDAK BERTANGGUNG JAWAB ATAS KLAIM, KERUSAKAN, ATAU TANGGUNG JAWAB LAINNYA, BAIK DALAM TINDAKAN KONTRAK, HUKUM ATAU LAINNYA, YANG TIMBUL DARI, ATAU SEHUBUNGAN DENGAN PERANGKAT LUNAK ATAU PENGGUNAAN ATAU HAL-HAL LAIN DALAM PERANGKAT LUNAK.