Соответствие двум критериям фильтра в Elasticsearch

Изменить

Я скопировал и вставил комментарий, который я разместил в ответ:

... запрос работает как надо. Я разместил этот вопрос в те времена, когда вы чувствуете себя загнанным в угол и не знаете, что еще попробовать. Ошибка была не в запросе и не в Elasticsearch, а из-за того, что я добавил новые поля в сообщение, а лямбда-функция не смогла индексировать новые сообщения (dynamic: false). В довершение всего у меня не было надлежащих предупреждений CloudWatch в журналах Lambda. Я понял это после анализа логов Kibana. Я предположил, что сообщения были созданы, потому что они появились в разделе комментариев (основное хранилище — Dynamo), но эти сообщения не были проиндексированы в Elasticsearch.

Исходный вопрос

У меня есть тысячи документов (сообщений), проиндексированных в Elasticsearch, и я пытаюсь сделать простой запрос:

SELECT *
FROM posts
WHERE comment LIKE '%comment%'
  AND created_at >= '2019-04-03'

Я пробовал разные подходы, используя запросы and и bool:

bool запрос

{
    "from": 0,
    "size": 10,
    "query": {
        "bool": {
            "must": [
                {
                    "match": {
                        "comment": "comment"
                    }
                },
                {
                    "range": {
                        "created_at": {
                            "gte": "2019-04-03T00:00:00.000Z"
                        }
                    }
                }
            ]
        }
    }
}

Результат:

Я получаю пустой набор результатов:

{
    "took": 3,
    "timed_out": false,
    "_shards": {
        "total": 5,
        "successful": 5,
        "skipped": 0,
        "failed": 0
    },
    "hits": {
        "total": 0,
        "max_score": null,
        "hits": []
    }
}

and запрос

{
    "from": 0,
    "size": 10,
    "query": {
        "filtered": {
            "filter": {
                "and": {
                    "filters": [
                        {
                            "term": {
                                "comment": "comment"
                            }
                        },
                        {
                            "range": {
                                "updated_at": {
                                    "gte": "2019-04-03T00:00:00.000Z"
                                }
                            }
                        }
                    ]
                }
            }
        }
    }
}

Результат:

Исключение разбора:

{
    "error": {
        "root_cause": [
            {
                "type": "parsing_exception",
                "reason": "no [query] registered for [filtered]",
                "line": 5,
                "col": 21
            }
        ],
        "type": "parsing_exception",
        "reason": "no [query] registered for [filtered]",
        "line": 5,
        "col": 21
    },
    "status": 400
}

Анализатор

Я использую следующий пользовательский анализатор:

{
  analysis: {
    analyzer: {
      custom_analyzer: {
        tokenizer: 'custom_tokenizer',
        filter: 'lowercase'
      }
    },
    tokenizer: {
      custom_tokenizer: {
        type: 'ngram',
        min_gram: 2,
        max_gram: 16,
        token_chars: [
          'letter',
          'digit',
          'punctuation',
          'symbol'
        ]
      }
    },
  }
}

Ожидаемый результат

Когда я запускаю отдельные запросы, один для match в comment, а другой для range в created_at, я получаю то, что он должен вернуть:

Поиск по тексту в comment:

{
    "from": 0,
    "size": 10,
    "query": {
        "bool": {
            "must": [
                {
                    "match": {
                        "comment": "comment"
                    }
                }
            ]
        }
    }
}

Результат:

{
    "took": 8,
    "timed_out": false,
    "_shards": {
        "total": 5,
        "successful": 5,
        "skipped": 0,
        "failed": 0
    },
    "hits": {
        "total": 888,
        "max_score": 1.9128458,
        "hits": [...]
    }
}

Поиск по дате range в created_at:

{
    "from": 0,
    "size": 10,
    "query": {
        "bool": {
            "must": [
                {
                    "range": {
                        "created_at": {
                            "gte": "2019-04-03T00:00:00.000Z"
                        }
                    }
                }
            ]
        }
    }
}

Результат:

{
    "took": 7,
    "timed_out": false,
    "_shards": {
        "total": 5,
        "successful": 5,
        "skipped": 0,
        "failed": 0
    },
    "hits": {
        "total": 19,
        "max_score": 1,
        "hits: [...]
    }
}

Я совершенно уверен, что есть сообщения, созданные после March 3rd с текстом comment в поле comment. Я добавил тестовые данные с комментариями, содержащими эту подстроку.


person Alejandro Rt    schedule 05.04.2019    source источник


Ответы (1)


Я не могу комментировать или отправлять сообщения напрямую, но можете ли вы предоставить дополнительные разъяснения?

Я попытался воссоздать проблему, так как ваш первый пример поиска должен работать, как и ожидалось. Чтобы подтвердить это, я создал простой индекс и добавил несколько записей для проверки различных предоставленных вами запросов:

POST demo/_doc
{
  "created_at": "2019-04-02T12:00:00.000Z",
  "comment": "contains comment"
}

POST demo/_doc
{
  "created_at": "2019-04-03T12:00:00.000Z",
  "comment": "contains another comment"
}

POST demo/_doc
{
  "created_at": "2019-04-03T12:00:00.000Z",
  "comment": "not what we are looking for"
}

Примечание. Я не стал возиться с пользовательским анализатором, так как ваши отдельные запросы показывают, что отдельные поиски работают правильно, так что это не должно иметь никакого значения.

Оттуда тестирование отдельных запросов дало ожидаемые результаты, и тестирование исходного запроса, который вы предоставили, также дало ожидаемые результаты:

Запрос:

GET demo/_search
{
  "from": 0,
  "size": 10,
  "query": {
    "bool": {
      "must": [
        {
          "match": {
            "comment": "comment"
          }
        },
        {
          "range": {
            "created_at": {
              "gte": "2019-04-03T00:00:00.000Z"
            }
          }
        }
      ]
    }
  }
}

Результат:

{
  "took" : 17,
  "timed_out" : false,
  "_shards" : {
    "total" : 5,
    "successful" : 5,
    "skipped" : 0,
    "failed" : 0
  },
  "hits" : {
    "total" : 1,
    "max_score" : 1.287682,
    "hits" : [
      {
        "_index" : "demo",
        "_type" : "_doc",
        "_id" : "-sxo72kBwpqm-gdssSYh",
        "_score" : 1.287682,
        "_source" : {
          "created_at" : "2019-04-03T12:00:00.000Z",
          "comment" : "contains another comment"
        }
      }
    ]
  }
}

Единственная возможность, которая бросается мне в глаза, это то, что вы указали в своем последнем заявлении, что есть сообщения, созданные «после 3 марта с текстом комментария в поле комментария», которые вы создали, но запросы на самом деле ищут сообщения с текстом комментария в комментарии. поле после апреля 3-го числа. Однако это вполне может быть опечаткой.

В качестве альтернативы, поскольку ваш второй запрос возвращает только 19 обращений (диапазон дат с учетом поля created_at), не могли бы вы просмотреть их, найти одно с полем комментария, содержащим текст comment, и вставить его или его фрагмент?

person James Pittiglio    schedule 05.04.2019
comment
Как вы упомянули, запрос работает как надо. Я разместил этот вопрос в те времена, когда вы чувствуете себя загнанным в угол и не знаете, что еще попробовать. Ошибка была не в запросе и не в Elasticsearch, а из-за того, что я добавил новые поля в сообщение, а лямбда-функция не смогла индексировать новые сообщения (dynamic: false). В довершение всего у меня не было надлежащих предупреждений CloudWatch в журналах Lambda. Я понял это после анализа логов Kibana. - person Alejandro Rt; 06.04.2019
comment
Полностью понимаю - я оказывался в таких ситуациях много раз - рад, что вы смогли решить эту проблему! - person James Pittiglio; 06.04.2019