#c# #lucene #lucene.net
#c# #lucene #lucene.net
Вопрос:
Я ищу способ найти термины, которые совпадают в документе, используя поиск по waldcard в Lucene. Я использовал объяснитель, чтобы попытаться найти термины, но это не удалось. Часть соответствующего кода приведена ниже.
ScoreDoc[] myHits = myTopDocs.scoreDocs;
int hitsCount = myHits.Length;
for (int myCounter = 0; myCounter < hitsCount; myCounter )
{
Document doc = searcher.Doc(myHits[myCounter].doc);
Explanation explanation = searcher.Explain(myQuery, myCounter);
string myExplanation = explanation.ToString();
...
Когда я выполняю поиск, скажем, в micro *, документы найдены, и они попадают в цикл, но myExplanation содержит НЕСООТВЕТСТВИЕ и никакой другой информации.
Как мне получить термин, который был найден в этом документе?
Любая помощь была бы очень признательна.
С уважением
Ответ №1:
class TVM : TermVectorMapper
{
public List<string> FoundTerms = new List<string>();
HashSet<string> _termTexts = new HashSet<string>();
public TVM(Query q, IndexReader r) : base()
{
List<Term> allTerms = new List<Term>();
q.Rewrite(r).ExtractTerms(allTerms);
foreach (Term t in allTerms) _termTexts.Add(t.Text());
}
public override void SetExpectations(string field, int numTerms, bool storeOffsets, bool storePositions)
{
}
public override void Map(string term, int frequency, TermVectorOffsetInfo[] offsets, int[] positions)
{
if (_termTexts.Contains(term)) FoundTerms.Add(term);
}
}
void TermVectorMapperTest()
{
RAMDirectory dir = new RAMDirectory();
IndexWriter writer = new IndexWriter(dir, new Lucene.Net.Analysis.Standard.StandardAnalyzer(), true);
Document d = null;
d = new Document();
d.Add(new Field("text", "microscope aaa", Field.Store.YES, Field.Index.ANALYZED,Field.TermVector.WITH_POSITIONS_OFFSETS));
writer.AddDocument(d);
d = new Document();
d.Add(new Field("text", "microsoft bbb", Field.Store.YES, Field.Index.ANALYZED, Field.TermVector.WITH_POSITIONS_OFFSETS));
writer.AddDocument(d);
writer.Close();
IndexReader reader = IndexReader.Open(dir);
IndexSearcher searcher = new IndexSearcher(reader);
QueryParser queryParser = new QueryParser("text", new Lucene.Net.Analysis.Standard.StandardAnalyzer());
queryParser.SetMultiTermRewriteMethod(MultiTermQuery.SCORING_BOOLEAN_QUERY_REWRITE);
Query query = queryParser.Parse("micro*");
TopDocs results = searcher.Search(query, 5);
System.Diagnostics.Debug.Assert(results.TotalHits == 2);
TVM tvm = new TVM(query, reader);
for (int i = 0; i < results.ScoreDocs.Length; i )
{
Console.Write("DOCID:" results.ScoreDocs[i].Doc " > ");
reader.GetTermFreqVector(results.ScoreDocs[i].Doc, "text", tvm);
foreach (string term in tvm.FoundTerms) Console.Write(term " ");
tvm.FoundTerms.Clear();
Console.WriteLine();
}
}
Комментарии:
1. Пришлось модифицировать класс TVM, чтобы использовать HashTable для C #. Спасибо, сработало так, как я хотел.
2. Вам не нужно изменять его с помощью Lucene. Net 2.9.4g в svn.apache.org/repos/asf/incubator/lucene.net/branches /…
Ответ №2:
Один из способов — использовать маркер; другим способом было бы имитировать то, что делает маркер, путем перезаписи вашего запроса путем вызова myQuery.rewrite() с соответствующим rewriter ; вероятно, это ближе по духу к тому, что вы пытались. Это перепишет запрос в BooleanQuery, содержащий все совпадающие термины; вы можете довольно легко извлечь слова из них. Этого достаточно, чтобы начать работу?
Вот идея, которую я имел в виду; извините за путаницу: переписывание запросов; здесь это не совсем уместно.
TokenStream tokens = TokenSources.getAnyTokenStream(IndexReader reader, int docId, String field, Analyzer analyzer);
CharTermAttribute termAtt = tokens.addAttribute(CharTermAttribute.class);
while (tokens.incrementToken()) {
// do something with termAtt, which holds the matched term
}
Комментарии:
1. На самом деле то, что я ищу, — это возможность получить только те термины, которые найдены в документе. Таким образом, если один документ содержит microscope, а другой содержит Microsoft, то, когда я нахожусь в первом документе, я должен получить только microscope, а когда я нахожусь во втором документе, я должен получить только Microsoft в качестве совпадающего термина. Ваше предложение дало бы мне все термины, которые соответствовали бы micro * в поле индекса. Я надеюсь, что смогу объяснить, что я ищу.