私はさまざまなフレーズを含むインデックス ストアを持っていますが、スペルが間違っているものもあります。
"Hallo World"
"Qick Brown Fox"
"Long tame no sees"
ブールクエリを使用してあいまい検索を実行していますが、一致した場合、一致したフレーズを取得する方法がわかりません。簡単に手に入るインデックスストアのフレーズだけが欲しいわけではありません。
たとえば、検索が ("Hello World" または "Keep it Real" または "Long Time no See") のブールクエリである場合、"Hallo World" および "Long tame no sees" が返されます。ただし、元のフレーズ「Hello World」と「Long Time no See」が一致したことも知っておく必要があります。何か案は?私の検索方法は次のとおりです(現在、フレーズ一致を返しますが、スペルミスのものを返します):-
public IEnumerable<DocumentWrapper> Search(List<string> fieldsToSearch, List<string> phrases, string path)
{
var luceneDir = FSDirectory.Open(new DirectoryInfo(path));
if (luceneDir == null)
{
Logging.Error("Invalid Index Directory during Search");
return null;
}
Logging.Information(string.Format("Searching for phrase(s): {0}", phrases.ToSeparatedList()));
var analyzer = new StandardAnalyzer(Version.LUCENE_30);
IndexReader indexReader;
try
{
indexReader = IndexReader.Open(luceneDir, true);
}
catch (FileNotFoundException)
{
Logging.Error("Lucene Directory has no items");
return null;
}
var matchedDocuments = new List<DocumentWrapper>();
try
{
var searcher = new IndexSearcher(indexReader);
MultiFieldQueryParser queryParser = null;
if (fieldsToSearch != null)
{
queryParser = new MultiFieldQueryParser(Version.LUCENE_30, fieldsToSearch.ToArray(), analyzer);
}
else
{
queryParser = new MultiFieldQueryParser(Version.LUCENE_30,
indexReader.GetFieldNames(
IndexReader.FieldOption.INDEXED_NO_TERMVECTOR).ToArray(),
analyzer);
}
//Add a fuzzy search using a tilde on each word in the phrase then 'AND' them together.
var booleanQueries = new List<BooleanQuery>();
foreach (var phrase in phrases)
{
var terms = phrase.Split(new[] {" "}, StringSplitOptions.RemoveEmptyEntries);
var booleanQuery = new BooleanQuery();
foreach (var term in terms)
{
booleanQuery.Add(queryParser.Parse(term.Replace("~", "") + "~"), Occur.MUST);
//'AND' the words in the phrase together.
}
booleanQueries.Add(booleanQuery);
}
//combine our boolean queries with 'OR' i.e. (word1 and word2 and word3) OR (word4 and word5) OR (word 6)
var combined = new BooleanQuery();
foreach (var query in booleanQueries)
{
combined.Add(query, Occur.SHOULD);
}
var maxHits = 100; //TODO - configurable
var collector = TopScoreDocCollector.Create(maxHits, true);
searcher.Search(combined, collector);
var hits = collector.TopDocs().ScoreDocs;
foreach (var t in hits)
{
var hitDoc = searcher.Doc(t.Doc);
var indexDoc = new DocumentWrapper();
foreach (var field in hitDoc.GetFields())
{
if (field.Name == "Score")
{
indexDoc.Contents.Add(field.Name, t.Score);
}
else
{
indexDoc.Contents.Add(field.Name, hitDoc.Get(field.Name));
}
}
matchedDocuments.Add(indexDoc);
}
}
catch
{
//TODO - Logging?
}
return matchedDocuments;
}