对于es的数据类型来说,如果它是一个简单类型,而咱们须要把简单类型进行检索,那么应该定义成 nested 类型,而对于它的检索,如果是非汇合数据,它与其它类型没有别离;而如果你的nested存储的数据是一个汇合,那在进行不等于这种操作时,就须要阐明一下了。

举例子

"id": "1","operate": [  {  "actionTime": "2017-03-21 11:57:37.700",  "operateType": "WangLu",  "wordNum": "3188",  "userName": "zidongluru"  },  {  "actionTime": "2017-03-21 11:57:37.700",  "operateType": "DaoRu",  "wordNum": "3188",  "userName": "qinbixue1609"  }]

对于下面的数据,其中operate是一个nested类型的,它存储数据为一个汇合,咱们查问operateType不等于WangLu的数据,如果间接应用not_must配合term,那后果是不对的,它会把这个文档失常返回,为什么?按说这个operate里是蕴含了 WangLu 的,如果蕴含它是不应该返回的;这就是es检索nested汇合解决不等于的问题,当会查问所有汇合中的元素,有一个不等于 WangLu 的,它就认为是不等于的,这与咱们的需要不合乎,所以要想其它办法。

script脚本检索nested汇合失败

{  "size": 5,   "_source": [    "Gid",    "Type",    "operate"  ],  "query": {    "bool": {      "must": [        {          "nested": {            "path": "operate",            "query": {              "script": {                "script": "doc['operate.operateType'].stream().map(o->o).filter(o->o=='YiJiaoSu').count()==0"               }            }          }        },        {          "term": {            "Gid": "1970325267114815"          }        }      ]    }  }}

应用function形式解决了这个问题

  • 参考

    https://cloud.tencent.com/developer/article/1973186

    https://cloud.tencent.com/developer/article/1973186

    https://stackoverflow.com/questions/54022283/elasticsearch-search-query-why-params-source-nested-field-size-is-not-workin

    {  "size": 5,  "_source": ["Gid","Type","operate"  ],  "query": {"bool": {  "must": [    {      "function_score": {        "query": {          "match_all": {}        },        "functions": [          {            "script_score": {              "script": {                "source": "params._source.operate.stream().map(o->o.operateType).filter(o->o=='YiJiaoSu').count()==0 ? 1 : 0"              }            }          }        ],        "min_score": 1      }    },    {      "term": {        "Id": "1970325267114815"      }    }  ]}  }}

    这种因为是汇合里的汇合再检索,所以须要和其它检索条件一起用,全表检索,性能比拟差。

翻译成java客户端代码

String val = "条件";  String name = "nested外部字段名";  String scoreStr = "params._source.operate==null || params._source.operate.stream().map(o->o." + name + ").filter(o->o=='" + val + "').count()==0? 1 : 0";  Script sc = new Script(ScriptType.INLINE, Script.DEFAULT_SCRIPT_LANG, scoreStr, MapUtil.empty());  ScriptScoreFunctionBuilder builder = new ScriptScoreFunctionBuilder(sc);  FunctionScoreQueryBuilder scoreBuilder = QueryBuilders.functionScoreQuery(builder);  scoreBuilder.setMinScore(1);  scoreBuilder.scoreMode(FunctionScoreQuery.ScoreMode.FIRST);  queryIncludeBuilder.must(scoreBuilder);