Elasticsearch 소스 분석 7 - Lucene 쿼리 인터페이스 범위 쿼리 호출

14902 단어 elasticsearchLucene

Elasticsearch 소스 분석 7 – Lucene 쿼리 인터페이스 범위 쿼리 호출

  • 소개
  • 조회 문법
  • 원본 분석

  • 소개


    범위 검색 특정 범위의 값이 일치하는 문서를 검색합니다.범위 조회는 최대 값과 최소 값을 포함하거나 포함하지 않을 수 있으며, 정렬은 사전 순서에 따라 정렬됩니다.범위 조회는 어떤 필드 값이 특정한 범위에 있는 문서를 찾을 수 있도록 합니다. 필드는 수치형일 수도 있고 문자열을 기반으로 할 수도 있습니다. (다른 아파치 루틴 조회에 비칠 수도 있습니다.)범위 조회는 단일 필드만 가능하며, 조회 매개 변수는 필드 이름에 봉인되어야 합니다.

    질의 문법


    예: year 필드에서 1700에서 1900까지의 모든 도서 찾기 {"query": {"range": {"year": {"gte": 1700, "lte": 1900}}}} 범위 조회는 다음 인자를 지원합니다.gte: 범위 조회는 필드 값이 이 매개 변수 값보다 크거나 같은 문서와 일치합니다.gt: 범위 조회는 이 매개 변수 값보다 필드 값이 큰 문서와 일치합니다.lte: 범위 조회는 필드 값이 이 매개 변수 값보다 작거나 같은 문서와 일치합니다.lt: 범위 조회는 필드 값이 이 매개 변수 값보다 작은 문서와 일치합니다.

    원본 분석

    '''(1)Elasticsearch code'''
    public class RangeQueryParser implements QueryParser {
    
        public static final String NAME = "range";
    
        @Override
        public Query parse(QueryParseContext parseContext) throws IOException, QueryParsingException {
            XContentParser parser = parseContext.parser();
    
            XContentParser.Token token = parser.nextToken();
            if (token != XContentParser.Token.FIELD_NAME) {
                throw new QueryParsingException(parseContext.index(), "[range] query malformed, no field to indicate field name");
            }
            String fieldName = parser.currentName();
            token = parser.nextToken();
            if (token != XContentParser.Token.START_OBJECT) {
                throw new QueryParsingException(parseContext.index(), "[range] query malformed, after field missing start object");
            }
    
            Object from = null;
            Object to = null;
            boolean includeLower = true;
            boolean includeUpper = true;
            float boost = 1.0f;
    
            String currentFieldName = null;
            while ((token = parser.nextToken()) != XContentParser.Token.END_OBJECT) {
                if (token == XContentParser.Token.FIELD_NAME) {
                    currentFieldName = parser.currentName();
                } else {
                    if ("from".equals(currentFieldName)) {
                        ''' '''
                        from = parser.objectBytes();
                    } else if ("to".equals(currentFieldName)) {
                        to = parser.objectBytes();
                    } else if ("include_lower".equals(currentFieldName) || "includeLower".equals(currentFieldName)) {
                        includeLower = parser.booleanValue();
                    } else if ("include_upper".equals(currentFieldName) || "includeUpper".equals(currentFieldName)) {
                        includeUpper = parser.booleanValue();
                    } else if ("boost".equals(currentFieldName)) {
                        boost = parser.floatValue();
                    } else if ("gt".equals(currentFieldName)) {
                        from = parser.objectBytes();                    
                        includeLower = false;
                    } else if ("gte".equals(currentFieldName) || "ge".equals(currentFieldName)) {
                        from = parser.objectBytes();
                        ''' '''
                        includeLower = true;
                    } else if ("lt".equals(currentFieldName)) {
                        to = parser.objectBytes();
                        ''' '''
                        includeUpper = false;
                    } else if ("lte".equals(currentFieldName) || "le".equals(currentFieldName)) {
                        ''' '''
                        to = parser.objectBytes();
                        includeUpper = true;
                    } else {
                        throw new QueryParsingException(parseContext.index(), "[range] query does not support [" + currentFieldName + "]");
                    }
                }
            }
    
            // move to the next end object, to close the field name
            token = parser.nextToken();
            if (token != XContentParser.Token.END_OBJECT) {
                throw new QueryParsingException(parseContext.index(), "[range] query malformed, does not end with an object");
            }
    
            Query query = null;
            MapperService.SmartNameFieldMappers smartNameFieldMappers = parseContext.smartFieldMappers(fieldName);
            if (smartNameFieldMappers != null) {
                if (smartNameFieldMappers.hasMapper()) {
                    //LUCENE 4 UPGRADE Mapper#rangeQuery should use bytesref as well? 
                    query = smartNameFieldMappers.mapper().rangeQuery(from, to, includeLower, includeUpper, parseContext);
                }
            }
            if (query == null) {
                ''' Lucene TermRangeQuery '''
                query = new TermRangeQuery(fieldName, BytesRefs.toBytesRef(from), BytesRefs.toBytesRef(to), includeLower, includeUpper);
            }
            query.setBoost(boost);
            return wrapSmartNameQuery(query, smartNameFieldMappers, parseContext);
        }
    }
    
    '''(2)Lucene code'''
    ''' TermRangeQuery TermRangeFilter '''
    public class TermRangeFilter extends MultiTermQueryWrapperFilter<TermRangeQuery> {
       ...
        /** * Constructs a filter for field <code>fieldName</code> matching * less than or equal to <code>upperTerm</code>. */
      public static TermRangeFilter Less(String fieldName, BytesRef upperTerm) {
          return new TermRangeFilter(fieldName, null, upperTerm, false, true);
      }
    
      /** * Constructs a filter for field <code>fieldName</code> matching * greater than or equal to <code>lowerTerm</code>. */
      public static TermRangeFilter More(String fieldName, BytesRef lowerTerm) {
          return new TermRangeFilter(fieldName, lowerTerm, null, true, false);
      }
    }
    '''(3)Lucene  '''
     public void testExclusive() throws Exception {
        ''' (A,C), , B '''
        Query query = TermRangeQuery.newStringRange("content", "A", "C", false, false);
        initializeIndex(new String[] {"A", "B", "C", "D"});
        IndexReader reader = DirectoryReader.open(dir);
        IndexSearcher searcher = newSearcher(reader);
        ScoreDoc[] hits = searcher.search(query, 1000).scoreDocs;
        assertEquals("A,B,C,D, only B in range", 1, hits.length);
        reader.close();
    
        initializeIndex(new String[] {"A", "B", "D"});
        reader = DirectoryReader.open(dir);
        searcher = newSearcher(reader);
        hits = searcher.search(query, 1000).scoreDocs;
        assertEquals("A,B,D, only B in range", 1, hits.length);
        reader.close();
    
        addDoc("C");
        reader = DirectoryReader.open(dir);
        searcher = newSearcher(reader);
        hits = searcher.search(query, 1000).scoreDocs;
        assertEquals("C added, still only B in range", 1, hits.length);
        reader.close();
      }
      public void testInclusive() throws Exception {
        ''' [A,C], ,A、B、C '''
        Query query = TermRangeQuery.newStringRange("content", "A", "C", true, true);
    
        initializeIndex(new String[]{"A", "B", "C", "D"});
        IndexReader reader = DirectoryReader.open(dir);
        IndexSearcher searcher = newSearcher(reader);
        ScoreDoc[] hits = searcher.search(query, 1000).scoreDocs;
        assertEquals("A,B,C,D - A,B,C in range", 3, hits.length);
        reader.close();
    
        initializeIndex(new String[]{"A", "B", "D"});
        reader = DirectoryReader.open(dir);
        searcher = newSearcher(reader);
        hits = searcher.search(query, 1000).scoreDocs;
        assertEquals("A,B,D - A and B in range", 2, hits.length);
        reader.close();
    
        addDoc("C");
        reader = DirectoryReader.open(dir);
        searcher = newSearcher(reader);
        hits = searcher.search(query, 1000).scoreDocs;
        assertEquals("C added - A, B, C in range", 3, hits.length);
        reader.close();
      }

    좋은 웹페이지 즐겨찾기