MongoDB でのファジー検索

Mehvish Ashiq 2024年2月16日
  1. ファジー検索とは
  2. MongoDB でサンプルコレクションを作成する
  3. MongoDB で $regex 演算子を使用してファジー検索を実行する
  4. MongoDB で $text クエリを使用してファジー検索を実行する
  5. MongoDB で JavaScript の Fuse.js ライブラリを使用してファジー検索を実行する
MongoDB でのファジー検索

今日は、ファジー検索と、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 のオブジェクトを作成し、keysincludeScore を持つオブジェクト personObjoptions の配列を渡して、ファジー検索を実行し、結果を取得します。

ここで、キーは検索が実行されるフィールドを指定します。includeScore はオプションですが、一致するスコアを示すため、これを使用することをお勧めします。

0 の場合、プログラムは完全に一致するものを見つけますが、1 のスコアは完全な不一致を示します。あなたはここですべてのオプションを見つけることができます。

最後に、接続を閉じることを忘れないでください。他にも探索できるライブラリはたくさんあります。

著者: Mehvish Ashiq
Mehvish Ashiq avatar Mehvish Ashiq avatar

Mehvish Ashiq is a former Java Programmer and a Data Science enthusiast who leverages her expertise to help others to learn and grow by creating interesting, useful, and reader-friendly content in Computer Programming, Data Science, and Technology.

LinkedIn GitHub Facebook