在Java中使用Lucene 9.10.0 MemoryIndex来摄取和搜索IntField并使用rangequery

问题描述 投票:0回答:1

我正在尝试使用 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();
    }
lucene full-text-search elasticsearch-analyzers
1个回答
0
投票

找到解决方案:

  1. 在MemoryIndex中添加字段时,添加为LongField(或IntField):
       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); }
  2. 添加自定义解析器:

公共类 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 字段,范围查询可以正常工作。

© www.soinside.com 2019 - 2024. All rights reserved.