# Поиск по двум связанным типам в одном индексе

**URL:** https://discuss.elastic.co/t/topic/156807
**Category:** Вопросы на русском языке
**Created:** [November 15, 2018, 8:27am UTC](https://discuss.elastic.co/t/topic/156807 "2018-11-15T08:27:56Z")
**Posts on this page:** 6
**Page:** 1

<div class="post-metadata">

### Author: ![smola](https://avatars.discourse-cdn.com/v4/letter/s/ac91a4/32.png) [@smola](https://discuss.elastic.co/u/smola)
#### Post date: [November 15, 2018, 8:27am UTC](https://discuss.elastic.co/t/topic/156807/1 "2018-11-15T08:27:56Z")

</div>

Коллеги, добрый день!  
Есть 2 типа в одном индексе. Пусть это будет Компании и Товары. У компании есть поле company\_name. Товары связаны с компаниями один ко многим, 1 компания - несколько товаров. Допустим, у товаров есть поле company\_id, в который заносим идентификатор компании.  
Нужно составить запрос, поиск по товарам, но чтобы искалось поисковое слово и с учетом поля company\_name в типе компании, аналог JOIN в mysql, примерно так:

`SELECT good_id FROM goods g INNER JOIN company c USING(company_id) WHERE c.company_name LIKE '%поисковое_слово%';`

Можно, конечно, дублировать поле company\_name и в типе Товары. Но так делать не хочется, т.к. каждый раз при изменении компанией ее названия придется менять его во всех товарах, которые к ней относятся.

Поиск приводит неизменно на nested запросы и has\_child/has\_parent запросы. Но никак не могу понять, чем они могут мне помочь..

Установленная версия ES 5.6.8  
Заранее спасибо всем откликнувшимся!)

---

<div class="post-metadata">

### Author: ![Igor\_Motov](https://sea2.discourse-cdn.com/elastic/user_avatar/discuss.elastic.co/igor_motov/32/45193_2.png) [@Igor\_Motov](https://discuss.elastic.co/u/Igor_Motov)
#### Post date: [November 15, 2018, 2:51pm UTC](https://discuss.elastic.co/t/topic/156807/2 "2018-11-15T14:51:22Z")

</div>

В случае с запросом [parent/child](https://www.elastic.co/guide/en/elasticsearch/reference/5.5/query-dsl-has-parent-query.html) ваш запрос будет транслироваться во что-то типа:

```auto
GET /test_index/goods/_search
{
    "query": {
        "has_parent" : {
            "parent_type" : "company",
            "query" : {
                "match" : {
                    "company_name" : "поисковое_слово"
                }
            }
        }
    }
}

```

Оба типа должны быть проиндексированы соответствующим образом, чтобы у них было отношение [parent/child](https://www.elastic.co/guide/en/elasticsearch/reference/5.6/mapping-parent-field.html). Надо также отметить, что в связи с переходом на 1 тип в одном индексе, начиная с версии 6.x лучше использовать [join](https://www.elastic.co/guide/en/elasticsearch/reference/6.5/parent-join.html) для этих целей.

---

<div class="post-metadata">

### Author: ![smola](https://avatars.discourse-cdn.com/v4/letter/s/ac91a4/32.png) [@smola](https://discuss.elastic.co/u/smola)
#### Post date: [November 20, 2018, 9:50am UTC](https://discuss.elastic.co/t/topic/156807/3 "2018-11-20T09:50:00Z")

</div>

Всё-таки не до конца я добил parent/child )) Игорь, спасибо, буду разбираться )

---

<div class="post-metadata">

### Author: ![smola](https://avatars.discourse-cdn.com/v4/letter/s/ac91a4/32.png) [@smola](https://discuss.elastic.co/u/smola)
#### Post date: [November 23, 2018, 12:25pm UTC](https://discuss.elastic.co/t/topic/156807/4 "2018-11-23T12:25:45Z")

</div>

Получилось, но наполовину... Запрос отрабатывает, но только по полю company\_name родительского типа. В реальной ситуации нужно еще искать и фильтровать и по полям ребенка.

Mapping (упрощенно):

```
$params = [
		'index' => $this->_index,
		'type' => parent::TYPE_GOOD_OFFERS,
		'body' => [
			parent::TYPE_GOOD_OFFERS => [
                                     '_parent' => [
                                         'type' => parent::TYPE_USERS
                                    ],
				'properties' => [
					'countryId' => [
						'type' => 'short'
					],
                                            'caption' => [
						'type' => 'text',
						'analyzer' => 'my_analyzer'
					],
					'description' => [
						'type' => 'text',
						'analyzer' => 'my_analyzer'
					]
				]
			]
		]
	];

	$this->_ElasticSearchClient->indices()->putMapping($params);

```

Запрос:

```
$this->_paramsForSearch = [
		'index' => $this->_index,
		'type' => $this->_type,
		'body' => [
			'size' => 10,
			'from' => 0,
			'sort' => $this->_getSortCommon(),
			'query' => [
			    'has_parent' => [
			        'parent_type' => parent::TYPE_USERS,
                    'query' => [
                        'bool' => [
                           'must' => [
                                'multi_match' => [
                                    'query' => $this->_searchText,
                                    'fields' => ['caption', 'description', 'companyName']
                                ]
                            ]
                        ]
                    ]
                ]
			]
		]
	];

```

Соответственно, при таком запросе он ищет только по полю companyName, игнорируя caption и description. Не могу понять, где тогда их указывать. Плюс мне еще нужно фильтровать по полю countryId (см. mapping), тоже не понятно куда вставлять этот кусок кода:

```
'term' => [
				'countryId' => 1
			]

```

Буду признателен за помощь

---

<div class="post-metadata">

### Author: ![Igor\_Motov](https://sea2.discourse-cdn.com/elastic/user_avatar/discuss.elastic.co/igor_motov/32/45193_2.png) [@Igor\_Motov](https://discuss.elastic.co/u/Igor_Motov)
#### Post date: [November 26, 2018, 4:28pm UTC](https://discuss.elastic.co/t/topic/156807/5 "2018-11-26T16:28:22Z")

</div>

Если поля `caption` и `description` относятся к `goods` то их не надо засовывать в `has_parent`:

```auto
"bool": {
  "must": [{
    "multi_match": {..... запрос по goods .... }
  }, {
    "has_parent": { .... запрос по company .... }
  }]
}

```

---

<div class="post-metadata">

### Author: ![system](https://us1.discourse-cdn.com/elastic/original/3X/1/a/1ac57faf039f6b580b3f104ef42a2a89e41014de.png) [@system](https://discuss.elastic.co/u/system)
#### Post date: [December 24, 2018, 4:28pm UTC](https://discuss.elastic.co/t/topic/156807/6 "2018-12-24T16:28:30Z")

</div>

This topic was automatically closed 28 days after the last reply. New replies are no longer allowed.
