Сопоставление терминов в документе при поиске с использованием поиска по шаблону

#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 * в поле индекса. Я надеюсь, что смогу объяснить, что я ищу.