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"
}
}
]
}
}
}
}
}
}
}