mongoose-fuzzy-searching 是一個簡單且輕量級的插件,可以在 MongoDB 中的文件中模糊搜尋。程式碼基於這篇文章。
使用 npm 安裝
$ npm i mongoose-fuzzy-searching
或使用紗線
$ yarn add mongoose-fuzzy-searching
在開始之前,為了獲得最佳實踐並避免任何問題,請正確處理所有棄用警告。
為了讓外掛程式建立索引,您需要將useCreateIndex
設為 true。下面的範例示範如何連接資料庫。
const options = {
useNewUrlParser : true ,
useUnifiedTopology : true ,
useFindAndModify : false ,
useCreateIndex : true ,
} ;
mongoose . Promise = global . Promise ;
return mongoose . connect ( URL , options ) ;
在下面的範例中,我們有一個User
集合,我們希望在firstName
和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 ) ;
}
結果按confidenceScore
鍵排序。您可以覆蓋此選項。
try {
const users = await User . fuzzySearch ( 'jo' ) . sort ( { age : - 1 } ) . exec ( ) ;
console . log ( users ) ;
} catch ( e ) {
console . error ( e ) ;
}
選項可以包含fields
和middlewares
。
Fields 屬性是強制性的,並且應該是Strings
數組或Objects
數組。
如果您想對所有欄位使用預設選項,只需將它們作為字串傳遞即可。
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' ] } ) ;
如果您想要覆蓋參數的任何預設選項,您可以將它們新增為物件並覆蓋您想要的任何值。下表包含該物件的預期鍵。
鑰匙 | 類型 | 預設 | 描述 |
---|---|---|---|
姓名 | 細繩 | 無效的 | 集合鍵名 |
最小尺寸 | 整數 | 2 | N 克最小尺寸。了解有關 N 元語法的更多信息 |
重量 | 整數 | 1 | 表示該欄位相對於其他索引欄位在文字搜尋分數方面的重要性。了解有關指數權重的更多信息 |
僅前綴 | 布林值 | 錯誤的 | 只回傳從單字開頭開始的 ngram。 (它給出更精確的結果) |
逃脫特殊字符 | 布林值 | 真的 | 從 N 元語法中刪除特殊字元。 |
鍵 | 數組[字串] | 無效的 | 如果集合屬性的類型是Object 或[Object] (請參閱範例),則可以定義哪些屬性將用於模糊搜尋 |
例子:
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' ] ,
} ,
] ,
} ) ;
中間件是一個可選Object
,可以包含自訂pre
中間件。該插件使用這些中間件來創建或更新模糊元素。這意味著如果您添加pre
中間件,它們將永遠不會被調用,因為插件會覆蓋它們。為了避免這個問題,您可以將自訂中間件傳遞到插件中。您的中間件將首先被呼叫。您可以傳遞的中間件有:
schema.pre("save", ...)
schema.pre("insertMany", ...)
schema.pre("update", ...)
schema.pre("updateOne", ...)
schema.pre("findOneAndUpdate", ...)
schema.pre("updateMany", ...)
如果你想添加上面的任何中間件,可以直接在插件上添加。
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
} ,
} ,
} ) ;
中間件也可以是非同步函數:
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)
}
}
} ) ;
模糊搜尋查詢可以用作static
函數,也可以用作helper
,它可以讓您將多個查詢連結在一起。任何一種情況下的函式名稱都是surprise、surprise、 fuzzySearch
。
實例方法最多可以接受三個參數。第一個是查詢,它可以是String
或Object
。此參數是必需的。第二個參數可以是包含任何附加查詢的Object
(例如age: { $gt: 18 }
),也可以是回呼函數。如果第二個參數是查詢,那麼第三個參數就是回呼函數。如果不設定回呼函數,結果將在 Promise 中傳回。
下表包含第一個參數的預期鍵(如果是物件)
鑰匙 | 類型 | 預設的 | 描述 |
---|---|---|---|
詢問 | 細繩 | 無效的 | 要搜尋的字串 |
最小尺寸 | 整數 | 2 | N 克最小尺寸。 |
僅前綴 | 布林值 | 錯誤的 | 只回傳從單字開頭開始的 ngram。 (它給出更精確的結果)前綴 |
精確的 | 布林值 | 錯誤的 | 匹配短語,而不是單一術語 |
例子:
/* 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 ) ;
}
} ) ;
您也可以使用查詢輔助函數,它類似於實例方法,但用於貓鼬查詢。查詢幫助器方法可讓您擴充 mongoose 的可連結查詢建構器 API。
查詢助手最多可接受兩個參數。第一個是查詢,它可以是String
或Object
。此參數是必需的。第二個參數可以是包含任何附加查詢的Object
(例如, age: { $gt: 18 }
),這是可選的。此幫助程式不接受回調函數。如果你傳遞一個函數,它會拋出一個錯誤。有關查詢助理的更多資訊。
例子:
const user = await User . find ( { age : { $gte : 30 } } )
. fuzzySearch ( 'jo' )
. exec ( ) ;
該插件為所選字段建立索引。在下面的範例中,新索引將為firstName_fuzzy
和lastName_fuzzy
。此外,每個文件都將具有欄位firstName_fuzzy
[String]和lastName_fuzzy
[String]。這些陣列將包含所選欄位的字謎。
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' ] } ) ;
換句話說,當您建立或更新文件時,該外掛程式會建立字謎詞。所有預先存在的文件都不會包含這些模糊數組,因此fuzzySearch
函數將無法找到它們。
為了為預先存在的文件建立字謎詞,您應該更新每個文件。下面的範例將firstName
屬性更新到集合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 ) ;
} ) ;
在前面的範例中,我們將firstName
和lastName
設為模糊屬性。如果從模糊欄位中刪除firstName
,則集合不會刪除firstName_fuzzy
陣列。如果要刪除每個文件上的數組,則必須取消設定該值。
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 } ) ;
} ) ;
我們使用 jest 進行所有單元測試和整合測試。
$ npm test
注意:這將串行運行所有套件,以避免資料庫上出現多個並發連接。
這將使用記憶體資料庫運行測試。如果您出於某種原因希望在 mongo 實例上使用實際連線執行測試,請新增環境變數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
麻省理工學院許可證
版權所有 (c) 2019 瓦西利斯帕拉斯
特此免費授予任何獲得本軟體及相關文件文件(「軟體」)副本的人不受限制地使用本軟體,包括但不限於使用、複製、修改、合併的權利、發布、散佈、再授權和/或銷售軟體的副本,並允許向其提供軟體的人員這樣做,但須滿足以下條件:
上述版權聲明和本授權聲明應包含在本軟體的所有副本或主要部分中。
本軟體以「現況」提供,不提供任何明示或暗示的保證,包括但不限於適銷性、特定用途的適用性和不侵權的保證。 IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE軟體.