ElasticSearch соответствует комбинация в массиве

Я внедряю ElasticSearch в свое приложение Laravel, используя пакет php от 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.

Мой текущий запрос выглядит следующим образом, однако он возвращает документы, в которых он имеет сеть с идентификатором 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]],
                        ],
                    ],
                ],
            ],
        ];

1 ответ

Решение

Вы должны указать, что объекты в networks массив должен храниться как отдельные объекты в индексе, это позволит вам выполнять поиск по отдельным network объекты. Вы можете сделать это, используя вложенный тип в Elasticsearch.

Кроме того, если вы делаете точные совпадения, лучше использовать фильтр, а не запрос, так как фильтры кэшируются и всегда дают вам лучшую производительность, чем запрос.

Создайте свой индекс с новым отображением. Использовать nested тип для networks массив.

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"
                                    }
                                }
                            ]
                        }
                    }
                }
            }
        }
    }
}
Другие вопросы по тегам