2012-02-28 4 views
0

Lucene_35로 필드를 검색하고 있습니다. 내 용어에서 얼마나 많은 단어가 필드와 일치하는지 알고 싶습니다. 예 : 내 필드는 입니다. "JavaServer Faces (JSF)는 웹 기반 사용자 인터페이스의 개발 통합을 단순화하기위한 Java 기반 웹 응용 프로그램 프레임 워크입니다.", 내 쿼리 용어가 "자바/JSF/프레임 워크/doesnotexist"입니다 만 "자바", "JSF"이후 3 결과를 원하는"프레임 워크" 필드에 존재한다.Lucene에서 일치하는 단어 수를 집계하십시오.

public void explain(String document, String queryExpr) throws Exception { 

     StandardAnalyzer analyzer = new StandardAnalyzer(Version.LUCENE_35); 
     Directory index = new RAMDirectory(); 
     IndexWriterConfig config = new IndexWriterConfig(Version.LUCENE_35, analyzer); 
     IndexWriter w = new IndexWriter(index, config); 
     addDoc(w, document); 
     w.close(); 
     String queryExpression = queryExpr; 
     Query q = new QueryParser(Version.LUCENE_35, "title", analyzer).parse(queryExpression); 

     System.out.println("Query: " + queryExpression); 
     IndexReader reader = IndexReader.open(index); 
     IndexSearcher searcher = new IndexSearcher(reader); 
     TopDocs topDocs = searcher.search(q, 10); 
     for (int i = 0; i < topDocs.totalHits; i++) { 
      ScoreDoc match = topDocs.scoreDocs[i]; 
      System.out.println("match.score: " + match.score); 
      Explanation explanation = searcher.explain(q, match.doc); //#1 
      System.out.println("----------"); 
      Document doc = searcher.doc(match.doc); 
      System.out.println(doc.get("title")); 
      System.out.println(explanation.toString()); 
     } 
     searcher.close(); 
    } 

위에서 언급 한 매개 변수 출력은 다음과 같습니다 :

0.021505041 = (MATCH) product of: 
    0.028673388 = (MATCH) sum of: 
    0.0064956956 = (MATCH) weight(title:java in 0), product of: 
     0.2709602 = queryWeight(title:java), product of: 
     0.30685282 = idf(docFreq=1, maxDocs=1) 
     0.8830299 = queryNorm 

....

 0.033902764 = (MATCH) fieldWeight(title:framework in 0), product of: 
     1.4142135 = tf(termFreq(title:framework)=2) 
     0.30685282 = idf(docFreq=1, maxDocs=1) 
     0.078125 = fieldNorm(field=title, doc=0) 
    0.75 = coord(3/4) 

나는이 세를 얻고 싶은 여기 내가 다음하고 간단한 예입니다/4 결과적으로.

감사합니다.

+0

Lucene과 어떤 관련이 있습니까? – jpountz

+0

죄송합니다 jpountz, 무슨 말씀입니까? LUCENE_35 및 RAMDirectory 인덱스를 사용하고 있습니다. 이제는 제가 필요로하는 것을 정확히 제공하지만 그 coord factor를 얻는 방법을 모르는 coord 요소가 있다는 것을 깨달았습니다. –

+0

귀하의 질문에 Lucene이 언급되지 않았으므로 귀하의 질문이 Lucene과 어떤 관계가 있는지 확신하지 못했습니다. 달성하고자하는 것에 대한 자세한 내용을 질문에 편집 할 수 있습니까? 색인은 어떻게 구성되어 있습니까? 성냥의 숫자에 따라 문서를 정렬 하시겠습니까? – jpountz

답변

7

다음과 같은 방법을 정의하여 루씬의 DefaultSimilarity을 대체함으로써이를 달성 할 수있다 : -> state.getBoost()

  • TF (주파수) -

    • computeNorm (필드 상태)> 주파수 == 0 ? 0 : 1
    • IDF (docFreq, numDocs) -> 1
    • COORD (중첩 maxOverlap) -> 1/maxOverlap
    • queryNorm (sumOfQuareWeights) -> 1

    이런 식으로 마지막 문서의 점수는 coor factor (1/maxOverlap)에 일치하는 용어의 수를 곱한 값으로 끝납니다.

    Directory dir = new RAMDirectory(); 
    
    Similarity similarity = new DefaultSimilarity() { 
        @Override 
        public float computeNorm(String fld, FieldInvertState state) { 
        return state.getBoost(); 
        } 
    
        @Override 
        public float coord(int overlap, int maxOverlap) { 
        return 1f/maxOverlap; 
        } 
    
        @Override 
        public float idf(int docFreq, int numDocs) { 
        return 1f; 
        } 
    
        @Override 
        public float queryNorm(float sumOfSquaredWeights) { 
        return 1f; 
        } 
    
        @Override 
        public float tf(float freq) { 
        return freq == 0f ? 0f : 1f; 
        } 
    }; 
    IndexWriterConfig iwConf = new IndexWriterConfig(Version.LUCENE_35, 
        new WhitespaceAnalyzer(Version.LUCENE_35)); 
    iwConf.setSimilarity(similarity); 
    IndexWriter iw = new IndexWriter(dir, iwConf); 
    Document doc = new Document(); 
    Field field = new Field("text", "", Store.YES, Index.ANALYZED); 
    doc.add(field); 
    for (String value : Arrays.asList("a b c", "c d", "a b d", "a c d")) { 
        field.setValue(value); 
        iw.addDocument(doc); 
    } 
    iw.commit(); 
    iw.close(); 
    
    IndexReader ir = IndexReader.open(dir); 
    IndexSearcher searcher = new IndexSearcher(ir); 
    searcher.setSimilarity(similarity); 
    BooleanQuery q = new BooleanQuery(); 
    q.add(new TermQuery(new Term("text", "a")), Occur.SHOULD); 
    q.add(new TermQuery(new Term("text", "b")), Occur.SHOULD); 
    q.add(new TermQuery(new Term("text", "d")), Occur.SHOULD); 
    
    TopDocs topDocs = searcher.search(q, 100); 
    System.out.println(topDocs.totalHits + " results"); 
    ScoreDoc[] scoreDocs = topDocs.scoreDocs; 
    for (int i = 0; i < scoreDocs.length; ++i) { 
        int docId = scoreDocs[i].doc; 
        float score = scoreDocs[i].score; 
        System.out.println(ir.document(docId).get("text") + " -> " + score); 
        System.out.println(searcher.explain(q, docId)); 
    } 
    ir.close(); 
    
  • +0

    고맙습니다. jpountz! 지금 제 경우에 결과를 가져 오는 방법을 알려주십시오. 그것은 Lucine, 내 첫 날입니다 그것에 대해 미안 해요 :) –

    +0

    안녕하세요 토스, 나는 내 대답을 업데이 트했습니다. – jpountz

    +0

    감사합니다, jpountz! –

    관련 문제