ElasticSearch 匹配数组中的组合

ElasticSearch match combination in array

我正在使用来自 ElasticSearch 的 php 包在我的 Laravel 应用程序中实施 ElasticSearch。

我的申请是一个小型工作板,目前我的工作文件如下所示:

{  
   "_index":"jobs",
   "_type":"job",
   "_id":"19",
   "_score":1,
   "_source":{  
      "0":"",
      "name":"Programmer",
      "description":"This is my first job! :)",
      "text":"Programming is awesome",
      "networks":[  
         {  
            "id":1,
            "status":"PRODUCTION",
            "start":"2015-02-26",
            "end":"2015-02-26"
         },
         {  
            "id":2,
            "status":"PAUSE",
            "start":"2015-02-26",
            "end":"2015-02-26"
         }
      ]
   }
}

如您所见,一个作业可以附加到多个网络。在我的搜索查询中,我想包括 WHERE network.id == 1 AND network.status == PRODUCTION.

我当前的查询看起来像这样,但是这个 returns 记录它有一个 id 1 的网络,如果它有任何状态为 PRODUCTION 的网络。无论如何,我可以在一个网络中强制两者都为真吗?

$query = [
            'index' => $this->index,
            'type' => $this->type,
            'body' => [
                'query' => [
                    'bool' => [
                        'must' => [
                            ['networks.id' => 1]],
                            ['networks.status' => 'PRODUCTION']]
                        ],
                        'should' => [
                            ['match' => ['name' => $query]],
                            ['match' => ['text' => $query]],
                            ['match' => ['description' => $query]],
                        ],
                    ],
                ],
            ],
        ];

您需要指定 networks 数组中的对象应作为单独的对象存储在索引中,这将允许您对单独的 network 对象执行搜索。您可以使用 Elasticsearch 中的 nested type 来执行此操作。

此外,如果您进行精确匹配,最好使用过滤器而不是查询,因为过滤器会被缓存并且总是比查询提供更好的性能。

使用新映射创建索引。对 networks 数组使用 nested 类型。

POST /test
{
    "mappings": {
        "job": {
            "properties": {
                "networks": {
                    "type": "nested",
                    "properties": {
                        "status": {
                            "type": "string",
                            "fields": {
                                "raw": {
                                    "type": "string",
                                    "index": "not_analyzed"
                                }
                            }
                        }
                    }
                }
            }
        }
    }
}

添加文档:

POST /test/job/1
{
    "0": "",
    "name": "Programmer",
    "description": "This is my first job! :)",
    "text": "Programming is awesome",
    "networks": [
        {
            "id": 1,
            "status": "PRODUCTION",
            "start": "2015-02-26",
            "end": "2015-02-26"
        },
        {
            "id": 2,
            "status": "PAUSE",
            "start": "2015-02-26",
            "end": "2015-02-26"
        }
    ]
}

由于您有嵌套类型,因此您需要使用嵌套过滤器。

POST /test/job/_search
{
    "query": {
        "filtered": {
            "query": {
                "match_all": {}
            },
            "filter": {
                "nested": {
                    "path": "networks",
                    "filter": {
                        "bool": {
                            "must": [
                                {
                                    "term": {
                                        "networks.id": "1"
                                    }
                                },
                                {
                                    "term": {
                                        "networks.status.raw": "PRODUCTION"
                                    }
                                }
                            ]
                        }
                    }
                }
            }
        }
    }
}