代码之家  ›  专栏  ›  技术社区  ›  Martin Čuka

ElasticSearch QueryBuilder不能出现奇怪的行为

  •  2
  • Martin Čuka  · 技术社区  · 6 年前

    根据文件

    一定不要 子句(查询)不能出现在匹配的文档中。

    我有这样的疑问:

    // searching for URI which contains smart and doesn't contain vip.vs.csin.cz
    BoolQueryBuilder builder = QueryBuilders.boolQuery();
    builder.must(QueryBuilders.termQuery(URI, "smart")));
    builder.mustNot(QueryBuilders.termQuery(URI, "vip.vs.csin.cz")));
    

    我的elasticsearch存储库中有两个URI

    1)

    /智能内景-vip与csin.cz:5080/smart/api/runtime/case/SC0000000000558648/record/generate/4327/by/SMOBVA002/as/true?espisRecordForm=模拟和帐号=2318031033/0800

    2)

    /smart/api/runtime/case/SC0000000000558648/record/generate/4327/by/SMOBVA002/as/true?espisRecordForm=模拟和帐号=2318031033/0800

    当我通过执行查询时

    elasticsearchTemplate.getClient().search(searchRequest);
    

    我回来了 0条记录 . 当我执行相同的查询时 不得 我回来了 2条记录。
    在基巴纳我可以写:

    uri: "smart" NOT uri: "vip.vs.csin.cz"
    

    1条记录

    我期望Java ElasticSearchClient也有同样的行为。如何筛选包含“0”的记录vip与csin.cz“以及为什么它过滤第二条记录,即使它不包含我指定的mustNot子句中的任何内容?

    编辑这是我的地图

    @Document(indexName = "audit-2018", type = "audit")
    public class Trace {
    
        @Id
        private String id;
        @Field(type = FieldType.Text)
        private String uri;
    
        // more columns, getter & setters
    }
    
    1 回复  |  直到 6 年前
        1
  •  1
  •   etarhan    6 年前

    您提供的Java代码使用 must must_not 子句,其中您正在执行术语查询。关于术语查询的问题是,它们取决于字段中的分析器,也就是术语查询的标准分析器 text (这是您的 uri 现场, read more here )字段将删除所有标点符号(换句话说就是单词中的点)并将单词拆分。 vip.vs.csin.cz 变成 vip vs csin cz . 这个 字段类型应该保留为全文搜索只,在你的情况下,我会去 keyword read more here )Kibana查询按预期工作的原因是,它实际上并没有执行terms查询,而是执行一个 query_string 包含lucene查询的查询: uri: "smart" NOT uri: "vip.vs.csin.cz" .

    所以你有几个选择来解决你的问题。您可以将查询条件更改为 match_phrase 查询,这将允许您保留标记化术语的顺序,并可能获得正确的结果。另一种选择是 query_string 在Java代码中使用query而不是terms查询,因为您已经确定这会给出正确的结果。

    不过,我建议的解决方案是使用 属于字段类型 ,因为此字段类型不会导致将字段值不需要的标记化为多个项。您可以阅读更多关于 字段类型 here . 这将使您在将来不再头痛,因为您知道您的查询与字段值完全“按原样”匹配。