Elasticsearch в типа bool запроса сочетать необходимо с или



в настоящее время я пытаюсь перенести приложение на основе solr в elasticsearch.



у меня есть этот lucene запрос



(( 
name:(+foo +bar)
OR info:(+foo +bar)
)) AND state:(1) AND (has_image:(0) OR has_image:(1)^100)


насколько я понимаю, это комбинация предложений MUST в сочетании с boolean или:



" получить все документы, содержащие (foo и бар в названии) или (foo и бар в информации). После этого отфильтруйте результаты по условию state=1 и повысьте документы, которые имеют изображение."



Я пытался использовать запрос bool с обязательным, но Я не могу получить boolean или в обязательные предложения. Вот что у меня есть:



GET /test/object/_search
{
"from": 0,
"size": 20,
"sort": {
"_score": "desc"
},
"query": {
"bool": {
"must": [
{
"match": {
"name": "foo"
}
},
{
"match": {
"name": "bar"
}
}
],
"must_not": [],
"should": [
{
"match": {
"has_image": {
"query": 1,
"boost": 100
}
}
}
]
}
}
}


Как вы можете видеть, должны условия для "информация" отсутствует.



есть ли у кого-нибудь решение?



большое спасибо.



** обновление **



я обновил свой запрос elasticsearch и избавился от этой оценки функции. Моя основная проблема все еще существует.

1017   6  

6 ответов:

  • или пишется "должен"
  • и пишется "должен"
  • также не пишется "should_not"

пример:

вы хотите увидеть все элементы, которые являются (круглые и (красный или синий)):

{
    "query": {
        "bool": {
            "must": [
                {
                    "term": {"shape": "round"},
                },
                {
                    "bool": {
                        "should": [
                            {"term": {"color": "red"}},
                            {"term": {"color": "blue"}}
                        ]
                    }
                }
            ]
        }
    }
}

вы также можете сделать более сложные версии или, например, если вы хотите, чтобы соответствовать по крайней мере 3 из 5, Вы можете указать 5 вариантов под "должен" и установить "minimum_should" из 3.

спасибо Глену Томпсону и Sebastialonso за то, что нашел, где мое гнездо было не совсем правильно раньше.

спасибо также Fatmajk за указание на то, что" термин "становится" матч " в ElasticSearch 6.

мне наконец удалось создать запрос, который делает именно то, что я хотел иметь:

отфильтрованный вложенный логический запрос. Я не уверен, почему это не документировано. Может быть, кто-то здесь может мне сказать?

вот запрос:

GET /test/object/_search
{
  "from": 0,
  "size": 20,
  "sort": {
    "_score": "desc"
  },
  "query": {
    "filtered": {
      "filter": {
        "bool": {
          "must": [
            {
              "term": {
                "state": 1
              }
            }
          ]
        }
      },
      "query": {
        "bool": {
          "should": [
            {
              "bool": {
                "must": [
                  {
                    "match": {
                      "name": "foo"
                    }
                  },
                  {
                    "match": {
                      "name": "bar"
                    }
                  }
                ],
                "should": [
                  {
                    "match": {
                      "has_image": {
                        "query": 1,
                        "boost": 100
                      }
                    }
                  }
                ]
              }
            },
            {
              "bool": {
                "must": [
                  {
                    "match": {
                      "info": "foo"
                    }
                  },
                  {
                    "match": {
                      "info": "bar"
                    }
                  }
                ],
                "should": [
                  {
                    "match": {
                      "has_image": {
                        "query": 1,
                        "boost": 100
                      }
                    }
                  }
                ]
              }
            }
          ],
          "minimum_should_match": 1
        }
      }    
    }
  }
}

в псевдо-SQL в:

SELECT * FROM /test/object
WHERE 
    ((name=foo AND name=bar) OR (info=foo AND info=bar))
AND state=1

пожалуйста, имейте в виду, что это зависит от вашего анализа поля документа и сопоставлений, как name=foo внутренне обрабатывается. Это может варьироваться от нечеткого строгого поведение.

"minimum_should_match": 1 говорит, что по крайней мере один из операторов should должен быть истинным.

Это утверждение означает, что всякий раз, когда в результирующем наборе есть документ, содержащий has_image:1, он увеличивается на коэффициент 100. Это изменяет порядок результатов.

"should": [
  {
    "match": {
      "has_image": {
        "query": 1,
        "boost": 100
      }
    }
   }
 ]

весело ребята :)

используя выше я вам

[term] malformed query, expected [END_OBJECT] but found [FIELD_NAME]

это сработало для меня

обновлено для Elasticsearch 5.6.4 +

{
    "query": {
        "bool": {
            "must": [
                {"term": {"shape": "round"}},
                {"bool": {
                    "should": [
                        {"term": {"color": "red"}},
                        {"term": {"color": "blue"}}
                    ]
                }}
            ]
        }
    }
}

недавно мне тоже пришлось решить эту проблему, и после многих проб и ошибок я придумал это (в PHP, но карты непосредственно в DSL):

'query' => [
    'bool' => [
        'should' => [
            ['prefix' => ['name_first' => $query]],
            ['prefix' => ['name_last' => $query]],
            ['prefix' => ['phone' => $query]],
            ['prefix' => ['email' => $query]],
            [
                'multi_match' => [
                    'query' => $query,
                    'type' => 'cross_fields',
                    'operator' => 'and',
                    'fields' => ['name_first', 'name_last']
                ]
            ]
        ],
        'minimum_should_match' => 1,
        'filter' => [
            ['term' => ['state' => 'active']],
            ['term' => ['company_id' => $companyId]]
        ]
    ]
]

который сопоставляется с чем-то вроде этого в SQL:

SELECT * from <index> 
WHERE (
    name_first LIKE '<query>%' OR
    name_last LIKE '<query>%' OR
    phone LIKE  '<query>%' OR
    email LIKE '<query>%'
)
AND state = 'active'
AND company_id = <query>

ключ во всем этом -minimum_should_match настройка. Без этого то filter полностью переопределяет should.

надеюсь, это кому-то поможет!

ElasticSearch определенно ужасен, когда дело доходит до простых запросов, таких как AND, OR или IN. Но вы можете пойти умным путем и написать свой запрос как SQL, а затем преобразовать его в синтаксис ElasticSearch с помощью этого превосходного онлайн-инструмента:

SQL to ElasticSearch converter

https://www.toolsbuzz.com/query-converter

вы можете поблагодарить меня позже :)

$filterQuery = $this->queryFactory->create(QueryInterface::TYPE_BOOL, ['must' => $queries,'should'=>$queriesGeo]);

на must вам нужно добавить массив условий запроса, с которым вы хотите работать AND и should вам нужно добавить условие запроса, с которым вы хотите работать OR.

вы можете проверить это:https://github.com/Smile-SA/elasticsuite/issues/972

Comments

    Ничего не найдено.