web-dev-qa-db-ja.com

MongoDB全文検索+部分的な単語一致の回避策

Mongodbの全文検索では「blueberry」という単語で「blueberry」を見つけることができないため、ユーザーが「blue」から「blueberry」までの単語を完成できるようにしたいと考えています。そうするために、mongodbフルテキストインデックス内のすべての単語をクエリすることは可能ですか-> typeahead.jsの候補として単語を使用できますか?

26
KIC

言語ステミング テキスト検索では、アルゴリズムを使用して、共通のベースから派生した単語を関連付けようとします(たとえば、「running」は「run」と一致する必要があります)。これは、オートコンプリート機能に実装するプレフィックス一致(たとえば、「blue」が「blueberry」に一致)とは異なります。

MongoDBテキスト検索でtypeahead.jsを最も効果的に使用するには、先行入力でのprefetchサポートに焦点を当てることをお勧めします。

  • コレクションで使用される一般的な単語(おそらく使用頻度のカウント)を含むkeywordsコレクションを作成します。このコレクションを作成するには、テキスト検索インデックスがあるコレクション全体で Map/Reduce を実行し、定期的にWordリストを最新の状態に保ちます Incremental Map/Reduce =新しいドキュメントが追加されたとき。

  • keywordsコレクションから一意のキーワードを使用してアプリケーションにJSONドキュメントを生成させます(リストを管理可能/関連性を保つために、Wordの頻度に基づく「人気のある」キーワードに制限される場合があります)。

次に、typeaheadのprefetch機能を使用して、クライアント側のオートコンプリートに生成されたキーワードJSONを使用できます。

$('.mysearch .typeahead').typeahead({
  name: 'mysearch',
  prefetch: '/data/keywords.json'
});

typeahead.jsは、クライアント側の検索のためにlocalStorageにprefetch JSONデータをキャッシュします。検索フォームが送信されると、アプリケーションはサーバー側の MongoDBテキスト検索 を使用して、完全な結果を関連性の高い順序で返すことができます。

12
Stennie

私が今行っている簡単な回避策は、テキストをテキストインデックス配列として格納されている個々の文字に分割することです。

次に、$searchクエリクエリを再び文字に分割するだけです。

これは、長さが32未満の短い文字列でのみ機能することに注意してください。そうしないと、インデックス作成プロセスに非常に時間がかかり、新しいレコードを挿入するときにパフォーマンスが大幅に低下します。

4
Chen

インデックス内のすべての単語をクエリすることはできませんが、元のドキュメントのフィールドをクエリすることはできます。検索インデックス内の単語も常に完全な単語であるとは限りませんが、いずれにせよ語幹です。したがって、おそらくインデックスに「blueberry」は見つかりませんが、「blueberri」だけが見つかります。

1
Derick

これがこの問題に直面している一部の新しい人々に役立つかどうかわからない。

コレクションのサイズと利用可能なRAMに応じて、適切なインデックスを作成することにより、$ regexで検索できます。例:

db.collection.find( {query : {$regex: /querywords/}}).sort({'criteria': -1}).limit(limit)

次のようなインデックスが必要です。

db.collection.ensureIndex( { "query": 1, "criteria" : -1 } )

十分なメモリがある場合、これは本当に高速になる可能性があります。

お役に立てれば。

1
user2988332

データベースアーキテクチャの実装をまだ開始しておらず、解決策を模索している方は、Elasticsearchにアクセスしてください。構造的にmongodbに似たjsonドキュメント駆動型データベース。それは「Edge-ngram」アナライザーを備えています。これは本当に効率的であり、スペルミスの検索に対してあなたが意味したことをすばやく提供します。部分的に検索することもできます。

1
Mihir Bhende