10

Lucene クエリ構文では、* と ~ を次のような有効なクエリに結合したいと思います: bla~* //invalid query

意味:「bla」または「bla」に似たもので始まる単語を一致させてください。

更新:私が今行っていることは、小さな入力で機能し、次を使用することです(SOLRスキーマのスニペット):

<fieldtype name="text_ngrams" class="solr.TextField">
  <analyzer type="index">
        <tokenizer class="solr.WhitespaceTokenizerFactory"/>
        <filter class="solr.WordDelimiterFilterFactory" generateWordParts="1" generateNumberParts="1" catenateWords="1" catenateNumbers="1" catenateAll="0" splitOnCaseChange="0"/>
        <filter class="solr.LowerCaseFilterFactory"/>
        <filter class="solr.EdgeNGramFilterFactory" minGramSize="2" maxGramSize="15" side="front"/>
  </analyzer>
  <analyzer type="query">
        <tokenizer class="solr.WhitespaceTokenizerFactory"/>
        <filter class="solr.WordDelimiterFilterFactory" generateWordParts="1" generateNumberParts="1" catenateWords="0" catenateNumbers="0" catenateAll="0" splitOnCaseChange="0"/>
        <filter class="solr.LowerCaseFilterFactory"/>
  </analyzer>

SOLR を使用しない場合、これは次のことを行います。

Indextime : 私の (短い) 入力のすべてのプレフィックスを含むフィールドを作成して、データにインデックスを付けます。

Searchtime : プレフィックスはインデックスに明示的に存在するため、~ 演算子のみを使用します。

4

4 に答える 4

8

lucene の開発トランク (まだリリースされていません) には、AutomatonQuery を介して、このようなユース ケースをサポートするコードがあります。警告: API はリリースされる前に変更される可能性がありますが、アイデアは得られます。

あなたの場合の例を次に示します。

// a term representative of the query, containing the field. 
// the term text is not so important and only used for toString() and such
Term term = new Term("yourfield", "bla~*");

// builds a DFA that accepts all strings within an edit distance of 2 from "bla"
Automaton fuzzy = new LevenshteinAutomata("bla").toAutomaton(2);

// concatenate this DFA with another DFA equivalent to the "*" operator
Automaton fuzzyPrefix = BasicOperations.concatenate(fuzzy, BasicAutomata.makeAnyString());

// build a query, search with it to get results.
AutomatonQuery query = new AutomatonQuery(term, fuzzyPrefix);
于 2010-05-08T03:16:53.867 に答える
2

Lucene がこのようなものをサポートしているとは思いませんし、簡単な解決策があるとは思いません。

「あいまい」検索は、一定数の文字で動作しません。bla~たとえば、一致する可能性があるためblah、用語全体を考慮する必要があります。

できることは、クエリを取得bla~*して一連の OR クエリに変換するクエリ拡張アルゴリズムを実装することです。

bla* OR blb* OR blc OR .... etc.

しかし、文字列が非常に短い場合、またはいくつかのルールに基づいて展開を狭めることができる場合にのみ、それは実際に実行可能です.

または、プレフィックスの長さが固定されている場合は、部分文字列を含むフィールドを追加して、そのフィールドであいまい検索を実行できます。それはあなたが望むものを与えるでしょうが、ユースケースが十分に狭い場合にのみ機能します.

これが必要な理由を正確に指定していません。おそらくそうすることで、他の解決策が引き出されるでしょう。

私が考えることができる 1 つのシナリオは、さまざまな形式の単語を扱うことです。たとえば、検索carcars.

単語ステマーが利用できるので、これは英語で簡単です。他の言語では、不可能ではないにしても、単語ステマーを実装することは非常に困難です。

ただし、このシナリオでは (適切な辞書にアクセスできると仮定して) 検索語を検索し、プログラムで検索を拡張して、単語のすべての形式を検索できます。

たとえば、検索carsは に変換されcar OR carsます。これは、少なくとも 1 つの検索エンジンで私の言語にうまく適用されていますが、実装するのは明らかに簡単ではありません。

于 2010-04-13T16:38:19.087 に答える
1

これは住所検索サービス用であり、部分的に入力された、または誤って入力された可能性のある番地/都市名など(任意の組み合わせ)に基づいて住所を提案したいと思います。(ajaxを考えてみてください。ユーザーは、テキストフィールドに住所の一部を入力します)

この場合、部分的な文字列(番地)が「短い」より長くなる可能性があるため、提案されたクエリ拡張はおそらくそれほど実現可能ではありません:)

正規化

私が考えることができる1つの可能性は、あいまい検索の代わりに文字列「正規化」を使用し、それをワイルドカードクエリと単純に組み合わせることです。の住所

"miklabraut 42, 101 reykjavík""miklabrat 42 101 rekavik"、正規化するとになります。

だから、このようなインデックスを構築する

1)「正規化された」バージョンのストリート名、都市名などを含むレコードを使用して、ドキュメントごとに1つのストリートアドレス(1つまたは複数のフィールド)を使用してインデックスを作成します。

そして、このようにインデックスを検索します

mikl reyk2)クエリの形成に使用される入力文字列(例)を正規化します(例mik rek)。3)ワイルドカードopを使用して検索を実行し(つまりmik* AND rek*)、あいまいな部分を除外します。

正規化アルゴリズムが十分に優れていれば、それは飛ぶでしょう:)

于 2010-04-13T19:48:08.423 に答える
0

ワイルドカードとあいまいクエリを組み合わせたいということですか? OR 条件を使用してブールクエリを使用して結合できます。次に例を示します。

BooleanQuery bq = new BooleanQuery();

Query q1 = //here goes your wildcard query
bq.Add(q1, BooleanClause...)

Query q2 = //here goes your fuzzy query
bq.Add(q2, BooleanClause...)
于 2010-04-13T16:40:51.640 に答える