• 打通es及lucene应用,lucene应用es Query,结合非queryString查询(二)


    其实可以减小难度,直接以lucene语法,mod_date:[20020101 TO 20030101],构造一个rangeQuery

    或直接构造RangFieldQuery实例

    lucene语法的range构造示例

    https://lucene.apache.org/core/7_7_0/queryparser/org/apache/lucene/queryparser/classic/package-summary.html#package.description

    因为主要目标是兼容es,为了复用es的查询语句,减少些工作量,因此想办法实现es的json解析 rangeQuery

    方法受保护,不过Builder可以直接用 BooleanQuery.Builder booleanQuery = new BooleanQuery.Builder();

    protected Builder newBooleanQuery() {
        return new Builder();
    }
    
    @Test
        public void textAndRangeQuery() throws Exception {
            AbstractBuilderTestCase c = new AbstractBuilderTestCase();
            c.beforeTest();
            QueryShardContext qc = AbstractBuilderTestCase.createShardContext();
            //实例构造
            String query =
                    "{
    " +
                            "    "range":{
    " +
                            "        "rangeFieldName": {
    " +
                            "            "gt": 1
    " +
                            "        }
    " +
                            "    }
    " +
                            "}";
            JsonParser jsonParser=new JsonParser(qc.getXContentRegistry());
            org.elasticsearch.index.query.QueryBuilder queryBuilder=jsonParser.parseQuery(query);
            Query rqbFromJson=queryBuilder.toQuery(qc);
    
            Query textQuery = EsQueryStringToLucene.parseLuceneQuery("(("中国" OR "美国") NOT ("渔船" OR "调查"))","textFieldName",new StandardAnalyzer());
            BooleanQuery.Builder booleanQuery = new BooleanQuery.Builder();
    
            booleanQuery.add(rqbFromJson,BooleanClause.Occur.SHOULD);
            booleanQuery.add(textQuery,BooleanClause.Occur.SHOULD);
    
            Query compileQuery=booleanQuery.build();
            System.out.println("to Query : "+compileQuery);
        }
    

    输出

    to Query : rangeFieldName:{1 TO *] ((textFieldName:"中 国" textFieldName:"美 国") -(textFieldName:"渔 船" textFieldName:"调 查"))

    任务完成

    本来为快速完成queryString 走的作减法的方向,但现在添加RangeQuery等结构化查询,又开始作加法

    另外这是分别手动聚合了两类查询,es官方可以将包含多类查询的dsl构造为一个Query的,这个方向又需要做更多加法


    之前还留了个尾巴

    queryString之前是通过QueryStringQueryParser 直接构建

        public static Query parseLuceneQuery(String esQueryStringPharse,String filedName, Analyzer analyzer) throws Exception {
            AbstractBuilderTestCase c = new AbstractBuilderTestCase();
            c.beforeTest();
            QueryShardContext qc = AbstractBuilderTestCase.createShardContext();
            QueryStringQueryParser queryStringQueryParser = new QueryStringQueryParser(qc, filedName);
            queryStringQueryParser.setForceAnalyzer(analyzer);
            queryStringQueryParser.setMultiFields(Arrays.asList(filedName));
            Query query = queryStringQueryParser.parse(esQueryStringPharse);
            return query;
        }
    

    非分词字段,类似RangeQueryBuilder 都不存在对应的Parser ,QueryStringQueryParser 是否也可以通过QueryStringQueryBuilder构造呢,这样和其他的统一

    很乐观的觉得应该是可以的

    然而翻车了

    因为现有的方案需要设置QueryStringQueryParser的属性

    官方是QueryStringQueryParser通过mapping 获取analyzer和fileds,我这里跳过了mapping信息,是外部添加的

        QueryStringQueryParser queryStringQueryParser = new QueryStringQueryParser(qc, filedName);
        queryStringQueryParser.setForceAnalyzer(analyzer);
        queryStringQueryParser.setMultiFields(Arrays.asList(filedName));
    
    protected Query doToQuery(QueryShardContext context) throws IOException {
        String rewrittenQueryString = this.escape ? QueryParser.escape(this.queryString) : this.queryString;
        if (this.fieldsAndWeights.size() > 0 && this.defaultField != null) {
            throw this.addValidationError("cannot use [fields] parameter in conjunction with [default_field]", (QueryValidationException)null);
        } else {
            boolean isLenient = this.lenient == null ? context.queryStringLenient() : this.lenient;
            QueryStringQueryParser queryParser;
            if (this.defaultField != null) {
                if (Regex.isMatchAllPattern(this.defaultField)) {
                    queryParser = new QueryStringQueryParser(context, this.lenient == null ? true : this.lenient);
                } else {
                    queryParser = new QueryStringQueryParser(context, this.defaultField, isLenient);
                }
            } 
    }
    

    而源码里是在doToQuery方法内部new QueryStringQueryParser的实例,我在外部不好为queryParser 添加属性,而且不是一处两种,很多地方都会new QueryStringQueryParser

    需要调整QueryStringQueryBuilder和QueryStringQueryParser,真调起来并不难,比如QueryStringQueryBuilder 新增构造参数analyzer和filedNames,再把所有QueryStringQueryBuilder内的QueryStringQueryParser,设置上analyzer和filedNames

    只是想尽量和es源码保证一致,越少的变化越好,因此,既然QueryStringQueryParser已经可用,那就不做这类操作了

    以后看有没有这样操作的必要


    之前只验证了rangeQuery,但是es原生的所有Query 并不完全都支持

    目前已知的 exists 和nested类的不支持

  • 相关阅读:
    python的dict和set
    python基础之dict和set
    python基础之条件判断和循环
    mongodb安装和配置,遇到问题和解决方法
    mybatis12--一级缓存
    mybatis11--多对多关联查询
    mybatis10--自连接多对一查询
    mybatis09--自连接一对多查询
    mybatis08--关联查询多对一
    mybatis07--关联查询一对多
  • 原文地址:https://www.cnblogs.com/zihunqingxin/p/14471732.html
Copyright © 2020-2023  润新知