我在我的java应用程序中使用了Lucene算法来查找索引中的匹配字符串。 我已经从所有匹配中取得了前5个顶级文档,但我想检查或计算原始字符串和匹配字符串的匹配存在。 在Lucene中可能吗? Lucene有任何方法可以找出它吗? 例如: -在Lucene中计算匹配字符串百分比
original string = I am good.
matching string = am good.
% of matching = 95
我在我的java应用程序中使用了Lucene算法来查找索引中的匹配字符串。 我已经从所有匹配中取得了前5个顶级文档,但我想检查或计算原始字符串和匹配字符串的匹配存在。 在Lucene中可能吗? Lucene有任何方法可以找出它吗? 例如: -在Lucene中计算匹配字符串百分比
original string = I am good.
matching string = am good.
% of matching = 95
当你说匹配百分比,你是什么意思?如果您想知道原始文本中包含多少文字(例如,您的案例中包含3个文字中的2个) 那么您可以使用term vectors完成工作,获取字段和文档的术语矢量并迭代超过条款,看看你正在寻找的内容是否有条款。或者甚至你可以存储字符串并获取整个内容并进行数学计算(如果存储不是问题)。 当前lucene使用vector space model(将从版本6x更改为BM25)来计算分数,并给出ScroeDoc 的匹配分数。但是,如果分数doc足够,那么使用它将给出十进制值。
如果这不能回答这个问题,那么给出更多关于如何用样本进行计算的细节。
希望这会有所帮助。
PS的,我已经写了简单的脚本,所以你可以看到和纠正您的需求:
package org.query;
import org.apache.lucene.analysis.Analyzer;
import org.apache.lucene.analysis.TokenStream;
import org.apache.lucene.analysis.core.WhitespaceAnalyzer;
import org.apache.lucene.analysis.tokenattributes.TermToBytesRefAttribute;
import org.apache.lucene.document.Document;
import org.apache.lucene.document.Field;
import org.apache.lucene.document.FieldType;
import org.apache.lucene.index.*;
import org.apache.lucene.search.*;
import org.apache.lucene.store.RAMDirectory;
import org.apache.lucene.util.BytesRef;
import org.junit.Before;
import org.junit.Test;
import java.util.HashSet;
import java.util.Set;
/**
* Created by ekamolid on 11/2/2015.
*/
public class LevenshteinTest {
private RAMDirectory directory;
private IndexSearcher searcher;
private IndexReader reader;
private Analyzer analyzer;
@Before
public void setUp() throws Exception {
directory = new RAMDirectory();
analyzer = new WhitespaceAnalyzer();
IndexWriter writer = new IndexWriter(directory, new IndexWriterConfig(analyzer));
Document doc = new Document();
FieldType fieldType = new FieldType();
fieldType.setIndexOptions(IndexOptions.DOCS_AND_FREQS);
fieldType.setStoreTermVectors(true);
doc.add(new Field("f", "the quick brown fox jumps over the lazy dog", fieldType));
writer.addDocument(doc);
doc = new Document();
doc.add(new Field("f", "the quick red fox jumps over the sleepy cat", fieldType));
writer.addDocument(doc);
doc = new Document();
doc.add(new Field("f", "quiick caar went xyztz dog", fieldType));
writer.addDocument(doc);
writer.close();
reader = DirectoryReader.open(directory);
searcher = new IndexSearcher(reader);
}
public static int distance(String a, String b) { //code is taken from http://rosettacode.org/wiki/Levenshtein_distance#Java
a = a.toLowerCase();
b = b.toLowerCase();
// i == 0
int[] costs = new int[b.length() + 1];
for (int j = 0; j < costs.length; j++)
costs[j] = j;
for (int i = 1; i <= a.length(); i++) {
// j == 0; nw = lev(i - 1, j)
costs[0] = i;
int nw = i - 1;
for (int j = 1; j <= b.length(); j++) {
int cj = Math.min(1 + Math.min(costs[j], costs[j - 1]), a.charAt(i - 1) == b.charAt(j - 1) ? nw : nw + 1);
nw = costs[j];
costs[j] = cj;
}
}
return costs[b.length()];
}
@Test
public void test1() throws Exception {
String s = "quick caar dog";
TokenStream tokenStream = analyzer.tokenStream("abc", s);
TermToBytesRefAttribute termAttribute = tokenStream.getAttribute(TermToBytesRefAttribute.class);
Set<String> stringSet = new HashSet<>();
tokenStream.reset();
BooleanQuery.Builder builder = new BooleanQuery.Builder();
while (tokenStream.incrementToken()) {
stringSet.add(termAttribute.getBytesRef().utf8ToString());
Query query = new FuzzyQuery(new Term("f", termAttribute.getBytesRef().utf8ToString()), 2); //search only 2 edits
builder.add(query, BooleanClause.Occur.SHOULD);
}
TopDocs hits = searcher.search(builder.build(), 10);
int exactMatch = 0;
int match1 = 0;
int match2 = 0;
for (ScoreDoc scoreDoc : hits.scoreDocs) {
exactMatch = match1 = match2 = 0;
Terms terms = reader.getTermVector(scoreDoc.doc, "f");
TermsEnum termsEnum = terms.iterator();
while (true) {
BytesRef bytesRef = termsEnum.next();
if (bytesRef == null) {
break;
}
String str = bytesRef.utf8ToString();
if (stringSet.contains(str)) {
exactMatch++;
continue;
}
for (String s1 : stringSet) {
int distance = distance(s1, str);
if (distance <= 1) {
match1++;
} else if (distance <= 2) {
match2++;
}
}
}
System.out.print(" doc=" + scoreDoc.doc);
System.out.print(" exactMatch=" + exactMatch);
System.out.print(" match1=" + match1);
System.out.println(" match2=" + match1);
}
}
}
输出我得到的是:
doc=2 exactMatch=2 match1=1 match2=1
doc=1 exactMatch=1 match1=0 match2=0
doc=0 exactMatch=2 match1=0 match2=0
这是工作的代码,告诉多少字符完全匹配,它们中有多少个是1个字符差异和2个字符差异。因此,您可以根据您手上的数字来计算%。这可能会慢一点,因为您正在迭代文档,但是您应该将结果限制为特定数字(示例中为10
),因此速度不会太慢。
谢谢主席的帮助。主席先生,术语向量用于匹配每个术语,比如“好女孩”匹配“好”和“女孩”,但是如果输入字符串中有任何语音错误,该怎么办?例如: - “god grl”匹配到“好女孩”,那么我怎么才能找到匹配的字符串百分比? – Keng
@Keng我在那里添加了工作代码。核实。 – Elbek