我正在尝试使用 MemoryIndex 克服整数范围查询问题。摄取 2 个字段 status(字符串字段)和 portno(int 字段)。如果端口范围在 50 到 90 之间,则输入应该匹配。当我使用 portno 的字符串表示形式时,由于索引为字符串的数字而得到不需要的结果。但是当我尝试使用 IntField 作为 portno 时,它也不匹配范围内的有效数字。代码及输出如下:
标准:状态:开放且端口号:[50 TO 90]
端口号:4 匹配条件:假
端口号:5 匹配条件:假
端口号:6 匹配条件:true
端口号:7 匹配条件:true
端口号:8 匹配条件:true
端口号:9 匹配条件:true
端口号:49 匹配条件:假
端口号:50 匹配条件:true
端口号:89 匹配条件:true
端口号:90 匹配标准:true
端口号:91 匹配条件:假
端口号:100 匹配条件:假
=>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
标准:状态:开放且端口号:[50 TO 90]
端口号:4 匹配条件:假
端口号:5 匹配条件:假
端口号:6 匹配条件:假
端口号:7 匹配条件:假
端口号:8 匹配条件:假
端口号:9 匹配条件:假
端口号:49 匹配条件:假
端口号:50 匹配条件:假
端口号:89 匹配条件:假
端口号:90 匹配条件:假
端口号:91 匹配条件:假
端口号:100 匹配条件:假
import org.apache.lucene.analysis.core.WhitespaceAnalyzer;
import org.apache.lucene.document.Field;
import org.apache.lucene.document.IntField;
import org.apache.lucene.index.memory.MemoryIndex;
import org.apache.lucene.queryparser.classic.MultiFieldQueryParser;
import org.apache.lucene.search.IndexSearcher;
import org.apache.lucene.search.Query;
import org.apache.lucene.search.TopDocs;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
public class CriteriaEvaluatorTest {
private static void indexNumberAsString() {
List<Integer> ilist = List.of(4, 5, 6, 7, 8, 9, 49, 50, 89, 90, 91, 100);
String criteria = "status: Open AND portno: [50 TO 90]";
System.out.println("Criteria: " + criteria);
ilist.forEach(number -> {
MemoryIndex memoryIndex = new MemoryIndex();
WhitespaceAnalyzer analyzer = new WhitespaceAnalyzer();
Map<String, Object> fmap = new HashMap<>();
fmap.put("status", "Open");
fmap.put("portno", String.valueOf(number));
for (Map.Entry<String, Object> entry : fmap.entrySet()) {
String fldName = entry.getKey();
String fldValue = entry.getValue().toString();
memoryIndex.addField(fldName, fldValue, analyzer);
}
IndexSearcher indexSearcher = memoryIndex.createSearcher();
String[] fldArray = new String[3];
int j = 0;
for (String fld : fmap.keySet()) {
fldArray[j++] = fld;
}
MultiFieldQueryParser multiFieldQueryParser = new MultiFieldQueryParser(fldArray, analyzer);
try {
Query query = multiFieldQueryParser.parse(criteria);
TopDocs topDocs = indexSearcher.search(query, 1);
boolean result = topDocs.totalHits.value > 0;
System.out.println("portno: " + number + " Criteria matched: " + result);
} catch (Exception e) {
String message = e.getMessage();
}
}
);
}
private static void indexNumberAsIntPoint() {
List<Integer> ilist = List.of(4, 5, 6, 7, 8, 9, 49, 50, 89, 90, 91, 100);
String criteria = "status: Open AND portno: [50 TO 90]";
System.out.println("Criteria: " + criteria);
ilist.forEach(number -> {
MemoryIndex memoryIndex = new MemoryIndex(true, true);
WhitespaceAnalyzer analyzer = new WhitespaceAnalyzer();
Map<String, Object> fmap = new HashMap<>();
fmap.put("status", "Open");
fmap.put("portno", number);
for (Map.Entry<String, Object> entry : fmap.entrySet()) {
String fldName = entry.getKey();
String fldValue = entry.getValue().toString();
if (fldName.equals("portno")) {
IntField intField = new IntField("portno", number, Field.Store.YES);
memoryIndex.addField(intField, analyzer);
} else {
memoryIndex.addField(fldName, fldValue, analyzer);
}
}
IndexSearcher indexSearcher = memoryIndex.createSearcher();
String[] fldArray = new String[3];
int j = 0;
for (String fld : fmap.keySet()) {
fldArray[j++] = fld;
}
MultiFieldQueryParser multiFieldQueryParser = new MultiFieldQueryParser(fldArray, analyzer);
try {
Query query = multiFieldQueryParser.parse(criteria);
TopDocs topDocs = indexSearcher.search(query, 1);
boolean result = topDocs.totalHits.value > 0;
System.out.println("portno: " + number + " Criteria matched: " + result);
} catch (Exception e) {
String message = e.getMessage();
}
}
);
}
public static void main(String args[]) {
indexNumberAsString();
System.out.println("=>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>");
indexNumberAsIntPoint();
}
找到解决方案:
if(LONG_FIELDS.contains(fldName)) { LongField longField = new LongField(fldName, Long.valueOf(fldValue), Field.Store.YES); memoryIndex.addField(longField, analyzer); } else { memoryIndex.addField(fldName, fldValue, analyzer); }
公共类 CustomCriteriaParser 扩展 MultiFieldQueryParser {
public CustomCriteriaParser(String[] f, List<String> lflist, Analyzer a) {
super(f, a);
if (Utils.notNullAndEmpty(lflist)) {
this.longFields.addAll(lflist);
}
}
private List<String> longFields = new ArrayList<>();
protected Query getFieldQuery(String field, String queryText, boolean quoted) {
return newRangeQuery(field, queryText, queryText, true, true);
}
protected Query newRangeQuery(String field, String fromValue, String toValue, boolean startInclusive,
boolean endInclusive) {
if (this.longFields.contains(field)) {
return LongField.newRangeQuery(field, Long.valueOf(fromValue), Long.valueOf(toValue));
}
return (TermRangeQuery) super.newRangeQuery(field, fromValue, toValue, startInclusive, endInclusive);
}
}
因此,对于特定的 Long/Int 字段,范围查询可以正常工作。