Как правильно сортировать выдачу?

Использую прослойку elastica

Есть индекс с уличами и номерами домов.

Без указания параметров все ищется нормально.

$resultSet = $search->addIndex($this->_index)
    ->addType('street')
    ->search($text."*")
;

Как пытаюсь указать параметры ничего не находит.

     $query = new \Elastica\Query\Builder('{
        "query" : {
            "term" : { "street_name" : "'.$text.'" }
        },
        "sort": { "street_name": { "order": "desc" }}
    }');

    $query = new \Elastica\Query($query->toArray());

    $resultSet = $search->addIndex($this->_index)
        ->addType('street')
        ->search($query)
    ;

Подскажите как правильно сортировать выдачу?

Проблема не в сортировке - проблема в запросе. Попробуйте использовать запрос match вместо term. Запрос term не выполняет анализ запросов и поэтому может не вернуть ожидаемые результаты.

Спасибо за ответ, буду пробовать.

Ничего не получилось.

Давай начем тогда с начала.

Есть два поля в документе и надо найти документ, который совпадает по этим двум полям.

пробовал такой запрос, ни к чему не привел

{
    "query": {
        "bool": {
            "should": [
                { "match": { "id": "id" }},
                { "match": { "name": "name" }}
            ]
        }
    }
}

Так же не понятно ка искать если одно поле заполняется частично, реализуется механизм подсказок.

Как выглядит документ и схема индекса?

не вставляется с нормальной разметкой (

{
"geo" : {
"mappings" : {
"street" : {
"properties" : {
"parentguid" : {
"type" : "string"
},
"postalcode" : {
"type" : "string"
},
"street_name" : {
"type" : "string"
},
"street_shortname" : {
"type" : "string"
}
}
},
"city" : {
"properties" : {
"city_id" : {
"type" : "string"
},
"name" : {
"type" : "string"
},
"region_id" : {
"type" : "string"
}
}
}
}
}
}

в одном типе ищу по точному совпадению с parentguid и не полному street_name

документ создается так

$document = new \Elastica\Document($street->code, [ 'parentguid' => $street->parentguid, 'street_shortname' => $street->shortname, 'street_name' => $street->formalname, 'postalcode' => $street->postalcode ]);

Как то так?

curl -XDELETE "localhost:9200/test?pretty"
curl -XPUT "localhost:9200/test?pretty" -d '{
  "settings": {
    "number_of_replicas": 0,
    "number_of_shards": 1
  },
  "mappings" : {
    "street" : {
      "properties" : {
        "parentguid" : {
          "type" : "string",
          "index": "not_analyzed"
        },
        "postalcode" : {
          "type" : "string",
          "index": "not_analyzed"
        },
        "street_name" : {
          "type" : "string"
        },
        "street_shortname" : {
          "type" : "string"
        }
      }
    },
    "city" : {
      "properties" : {
        "city_id" : {
          "type" : "string",
          "index": "not_analyzed"
        },
        "name" : {
          "type" : "string"
        },
        "region_id" : {
          "type" : "string",
          "index": "not_analyzed"
        }
      }
    }
  }
}'
curl -XPUT "localhost:9200/test/street/1?pretty" -d '{
  "parentguid": "12345-67890",
  "street_name": "Main St."
}'
curl -XPOST "localhost:9200/test/_refresh?pretty"
curl -XGET "localhost:9200/test/street/_search?pretty" -d '{
    "query": {
        "bool": {
            "must": [
                { "match": { "parentguid": "12345-67890" }},
                { "match": { "street_name": "main" }}
            ]
        }
    }
}'

попробовал ранее такой вариант
отличалось только параметрами в mapping
почему то ищет толко при полном совпадении названии улицы

попробовал твой вариант, работает, может все из-за русской морфологии?

еще вопрос - можно ли как то журналировать get post запросы для отладки?

хотя нет, твой вариант тоже не рабочий

если ввести "street_name": "mai", то не найдет

Вы нигде не упоминали, что Вам необходим поиск по подстроке. Поиск по подстроке - это уже совсем другая история.

Посмотрите соседний топик. Я там привел пример поиска по подстрокам.

Возможно я не правилно описал ситуацию

в одном типе ищу по точному совпадению с parentguid и не полному street_name

по неполному совпадению в street_name и имелос ввиду.

Тогда пример с edgeNGram в соседнем топике должен для вас работать.

читал в интернете, что для русской морфологии ставятся плагины
особо разницы не заметил, это не актуально?

Морфология не актуальна для названий улиц, и даже может навредить. Когда Вы ищете по тексту, и в поиске задан термин повелецкий, то с помощью русской морфологии можно будет найти и текст со словам павелецком, и текст со словом павелецкая.

В случае поиска по географическим названиям, скорее всего, пользователь который ищет станцию метро "Пионерская" вряд ли будет заинтересован в нахождении "Пионерского" пруда, поэтому производить морфологический анализ бесполезно и даже, в некоторых случаях, вредно.

Снова возвращаюсь к этому вопросу

$mapping = [
			'code' => [
				'type' => 'string',
				'index' => 'not_analyzed'
			],
			'parentguid' => [
				'type' => 'string',
				'index' => 'not_analyzed'
			],
			'postalcode' => [
				'type' => 'string',
				'index' => 'not_analyzed'
			],
			'street_shortname' => [
				'type' => 'string',
				'index' => 'not_analyzed'
			],
			'street_name' => [
				'type' => 'string',
				'analyzer' => 'ngram_index_analyzer',
				'search_analyzer' => 'ngram_search_analyzer'
			],
			'full_name' => [
				'type' => 'string',
				'index' => 'not_analyzed'
			]
		];

index

			'number_of_shards' => 1,
			'number_of_replicas' => 0,
			'analysis' => [
				'analyzer' => [
					'ngram_index_analyzer' => [
						'tokenizer' => 'standard',
						'filter' => ['lowercase', 'ngram']
					],
					'ngram_search_analyzer' => [
						'tokenizer' => 'standard',
						'filter' => ['lowercase']
					],
				],
				'filter' => [
					'ngram' => [
						'type' => 'edgeNGram',
						'min_gram' => 3,
						'max_gram' => 50
					]
				]
			]

и сам запрос

            "query": {
                "bool": {
                    "must": [
                        { "match": { "parentguid": "'.$parentguid.'" }},
                        { "match": { "street_name": "'.$query.'" }}
                    ]
                }
            }

при поиске улицы: кузнецкий мост
выдает Кузнецкий Мост и Богатырский Мост

при поиске улицы зацепенский вал выдает что только можно где было вхождение

как организовать нормальный поиск без левых выдач?

Вы не могли бы задать этот вопрос на более техническом уровне. "Нормальный" -понятие растяжимое, и левая выдача для одного типа задач - правильная выдача для другого. Я понимаю, что точно определить, как оптимальный поиск должен работать достаточно сложно. Поэтому можно было бы начать с примера с данными, запросами, результатом, который этот пример выдает и ожидаемым результатом, который вы хотели бы видеть.

Я пытаюсь сделать систему подсказок как в яндкес или гугл картах

там же не выводится по искомой фразе еще много чего нерелеватного

если я набираю последовательно фразу Кузнецкий Мост

Набирав кузнецкий выдает Кузнецкий Мост
если дописываю мост уже выдает и Кузнецкий Мост и Богатырский Мост
разве это нормально?

Если вам важно совпадение по слову "мост", то это вполне нормально, тем более, что кузнецкий мост появляется в результатах перед богатырским. Если вам необходимо совпадение по все словам, которые появляются в запросе, то вам надо переключится на другой режим в запросе match. Например с использованием оператора and, если вам важно совпадение всех слов в запросе

"match": {
    "street_name": {
        "query": "кузнецкий мост",
        "operator" : "and"
    }
}

Или с использованием match_phrase если важен порядок слов:

"match_phrase": {
    "street_name": {
        "query": "Кузнецкий Мост"
    }
}

Но при этом кузнецкий мо вам больше ничего возвращать не будет, потому, что у вас n-gram начинаются с 3, а нужно, чтобы они начинались с 1.

Вариантов много. Надо только точно определиться, что является "нормальным" для вас. И, главное, не подходить к elasticsearch, как к какому-то магическому существу, которое может залезть к вам в голову и точно определить, что вы хотите найти. Тут никакой магии нет - все дело в простом совпадении генерируемых токенов при запросе и индексировании. И контроль над тем, как эти токены генерируются - в ваших руках. Если вы не хотите этот контроль, то лучше использовать более простые средства - анализатор standard и запрос match_phrase_prefix.

С operator стало все яснее, еще пробую другие варинаты.
Про минимальный лимит ngram вылетело из головы вообще )

Мне кажется если бы вы реализовали механизм запросов через sql было бы удобнее и понятнее.
Многое не понятно новичку, тк тут совсем другая идеология.
В том же sphinx все через sql и довольно быстро можно освоиться, с sql то все знакомы )

Так в этом-то и все дело! Если бы мы реализовали механизм запросов через sql, то пользователи бы стали пользоваться elasticsearch как реляционной базой, и ни к чему хорошему это бы не привело. Elasticsearch это поисковый движок, который использует совсем другие модели данных, которые базируются на совсем других математических моделях и алгоритмах, и поэтому он требует иного подхода к моделированию данных и построению запросов.