MongoDB でのファジー検索
- ファジー検索とは
- MongoDB でサンプルコレクションを作成する
-
MongoDB で
$regex
演算子を使用してファジー検索を実行する -
MongoDB で
$text
クエリを使用してファジー検索を実行する -
MongoDB で JavaScript の
Fuse.js
ライブラリを使用してファジー検索を実行する
今日は、ファジー検索と、MongoDB を使用してファジー検索を実行する方法について説明します。
まず、$regex
演算子と $text
クエリを使用します。さらに、Fuse.js
という名前の JavaScript ライブラリを使用して、ドキュメントをファジー検索する方法を学習します。
ファジー検索とは
ファジー検索を使用すると、完全には一致しないが、用語に厳密に一致するテキストを検索できます。検索語のつづりが間違っている場合でも、関連する結果を見つけるのに役立ちます。
たとえば、Google は、入力ミスがあった場合でも、検索された用語に関連するさまざまな Web ページを表示します。通常の式(regex とも呼ばれます)の使用も、ファジー検索を実装するための非常に有益で時間の節約になるアプローチです。
MongoDB でサンプルコレクションを作成する
ファジー検索を学ぶために、基本レベルから上級レベルまで始めます。それを実践するために、collection_one
という名前のサンプルコレクションを作成してみましょう。このコレクションには、ドキュメントごとに 1つのフィールド、つまり name
があります。
_id
は自動的に作成されます。それを作成する必要はありません。次のクエリを使用して同じことを行うことができます。
サンプルコード:
> db.createCollection('collection_one')
> db.collection_one.insertMany([
{ name : 'Mehvish Ashiq'},
{ name : 'Jennifer Johnson'},
{ name : 'Natalie Robinson'},
{ name : 'John Ferguson'},
{ name : 'Samuel Patterson'},
{ name : 'Salvatore Callahan'},
{ name : 'Mikaela Christensen'}
])
> db.collection_one.find()
出力:
{ "_id" : ObjectId("62939a37b3a0d806d251ddae"), "name" : "Mehvish Ashiq" }
{ "_id" : ObjectId("62939a37b3a0d806d251ddaf"), "name" : "Jennifer Johnson" }
{ "_id" : ObjectId("62939a37b3a0d806d251ddb0"), "name" : "Natalie Robinson" }
{ "_id" : ObjectId("62939a37b3a0d806d251ddb1"), "name" : "John Ferguson" }
{ "_id" : ObjectId("62939a37b3a0d806d251ddb2"), "name" : "Samuel Patterson" }
{ "_id" : ObjectId("62939a37b3a0d806d251ddb3"), "name" : "Salvatore Callahan" }
{ "_id" : ObjectId("62939a37b3a0d806d251ddb4"), "name" : "Mikaela Christensen" }
MongoDB で $regex
演算子を使用してファジー検索を実行する
サンプルコード:
> db.collection_one.find({"name": /m/})
出力:
{ "_id" : ObjectId("62939a37b3a0d806d251ddb2"), "name" : "Samuel Patterson" }
このコードでは、name
フィールドでファジー検索を実行し、name
フィールドに文字 m
が含まれているすべてのドキュメントを取得しました。
ご覧のとおり、m
の文字を含むレコードは 1つしかありませんが、M
(大文字)で始まるドキュメントがさらに 2つあります。これを処理するために、次のように i
修飾子を使用できます。これは、大文字と小文字を区別しない検索を実行します。
サンプルコード:
> db.collection_one.find({"name": /m/i})
出力:
{ "_id" : ObjectId("62939a37b3a0d806d251ddae"), "name" : "Mehvish Ashiq" }
{ "_id" : ObjectId("62939a37b3a0d806d251ddb2"), "name" : "Samuel Patterson" }
{ "_id" : ObjectId("62939a37b3a0d806d251ddb4"), "name" : "Mikaela Christensen" }
正しく設計された規則的な表現を持つことが非常に重要であることを示しました。そうしないと、誤解を招く結果が生じる可能性があります。次の方法でも同じことができます。
サンプルコード(大文字と小文字を区別しない検索):
> db.collection_one.find({'name': {'$regex': 'm','$options': 'i'}})
出力:
{ "_id" : ObjectId("62939a37b3a0d806d251ddae"), "name" : "Mehvish Ashiq" }
{ "_id" : ObjectId("62939a37b3a0d806d251ddb2"), "name" : "Samuel Patterson" }
{ "_id" : ObjectId("62939a37b3a0d806d251ddb4"), "name" : "Mikaela Christensen" }
同様に、name
が 2 文字の組み合わせで終わるすべてのドキュメントを on
として取得できます。
サンプルコード:
> db.collection_one.find({name:{'$regex' : 'on$', '$options' : 'i'}})
出力:
{ "_id" : ObjectId("62939a37b3a0d806d251ddaf"), "name" : "Jennifer Johnson" }
{ "_id" : ObjectId("62939a37b3a0d806d251ddb0"), "name" : "Natalie Robinson" }
{ "_id" : ObjectId("62939a37b3a0d806d251ddb1"), "name" : "John Ferguson" }
{ "_id" : ObjectId("62939a37b3a0d806d251ddb2"), "name" : "Samuel Patterson" }
MongoDB で $text
クエリを使用してファジー検索を実行する
$text
クエリは、collection_one
という名前のサンプルコレクションでは機能しません。これは、テキストインデックスがないためです。そこで、次のようにインデックスを作成します。
サンプルコード:
> db.collection_one.createIndex({name:"text"});
上記のステートメントは、指定されたコレクションがまだ存在しない場合にも作成します。カンマで区切られた 1つまたは複数のフィールドにインデックスを作成できることを忘れないでください。
次の例を参照してください。
db.collection_name.createIndex({name:"text", description:"text"});
インデックスが作成されると、以下のようにファジー検索を実行できます。
サンプルコード:
> db.collection_one.find({ $text: { $search: "Mehvish" } } )
出力:
{ "_id" : ObjectId("62939a37b3a0d806d251ddae"), "name" : "Mehvish Ashiq" }
MongoDB で JavaScript の Fuse.js
ライブラリを使用してファジー検索を実行する
サンプルコード(fuzzysearch.js
ファイルコード):
const Fuse = require('fuse.js')
var MongoClient = require('mongodb').MongoClient;
var url = 'mongodb://localhost:27017/';
MongoClient.connect(url, function(err, db) {
if (err) throw err;
var dbo = db.db('FuseFuzzySearch');
var personObj = [
{name: 'Mehvish Ashiq'}, {name: 'Jennifer Johnson'},
{name: 'Natalie Robinson'}, {name: 'John Ferguson'},
{name: 'Samuel Patterson'}, {name: 'Salvatore Callahan'},
{name: 'Mikaela Christensen'}
];
dbo.collection('person').insertMany(personObj, function(err, res) {
if (err) throw err;
});
const options = {includeScore: true, keys: ['name']}
const fuse = new Fuse(personObj, options);
const result = fuse.search('jahson');
console.log(result);
db.close();
});
出力:
[
{
item: { name: 'Jennifer Johnson', _id: 6293aa0340aa3b21483d9885 },
refIndex: 1,
score: 0.5445835311565898
},
{
item: { name: 'John Ferguson', _id: 6293aa0340aa3b21483d9887 },
refIndex: 3,
score: 0.612592665952338
},
{
item: { name: 'Natalie Robinson', _id: 6293aa0340aa3b21483d9886 },
refIndex: 2,
score: 0.6968718698752637
},
{
item: { name: 'Samuel Patterson', _id: 6293aa0340aa3b21483d9888 },
refIndex: 4,
score: 0.6968718698752637
}
]
このコード例では、最初に fuse.js
ライブラリをインポートしました。次に、MongoDB に接続しました。
何らかの理由で接続されていない場合は、エラーをスローします。それ以外の場合は、FuseFussySearch
という名前のデータベースを作成します。
次に、person
コレクションに挿入するすべてのドキュメントを含む personObj
という名前のオブジェクトを作成します。データの挿入中に問題が発生すると、エラーが生成されます。
上記のように、Fuse
のオブジェクトを作成し、keys
と includeScore
を持つオブジェクト personObj
と options
の配列を渡して、ファジー検索を実行し、結果を取得します。
ここで、キー
は検索が実行されるフィールドを指定します。includeScore
はオプションですが、一致するスコアを示すため、これを使用することをお勧めします。
0
の場合、プログラムは完全に一致するものを見つけますが、1
のスコアは完全な不一致を示します。あなたはここですべてのオプションを見つけることができます。
最後に、接続を閉じることを忘れないでください。他にも探索できるライブラリはたくさんあります。