Elasticsearch: найти документы, содержащие не больше терминов, чем в запросе - PullRequest
2 голосов
/ 03 апреля 2020

Если у меня есть документы:

1: { "name": "red yellow" }
2: { "name": "green yellow" }

Я бы хотел запросить «красно-коричневый желтый» и получить документ 1.

Я имею в виду, что запрос должен содержать как минимум форму терминов мой документ, но может содержать больше. Если в документе есть токен, которого нет в запросе, он не должен попадать.

Как я могу это сделать? Обратный путь легко ...

Ответы [ 2 ]

1 голос
/ 04 апреля 2020

Запрос на совпадение имеет тип boolean. Это означает, что предоставленный текст анализируется, и процесс анализа создает логический запрос из предоставленного текста. Минимальное количество необязательных предложений must для сопоставления может быть установлено с помощью параметра Minimum_should_match.

Чтобы узнать больше о запросе на совпадение , вы можете обратиться к Документация ES

Ниже приведено отображение поля name

{
"tests": {
    "mappings": {
        "properties": {
            "name": {
                "type": "text",
                "fields": {
                    "keyword": {
                        "type": "keyword",
                        "ignore_above": 256
                    }
                }
            }
        }
    }
}

}

Теперь при поиске "red brown yellow" из запроса ниже

POST tests/_search

{
"query": {
    "match": {
        "name": {
            "query": "red brown yellow",
            "minimum_should_match": "75%"
        }
    }
 }

}

Вы получите требуемый результат:

    {
  "took": 2,
  "timed_out": false,
  "_shards": {
    "total": 1,
    "successful": 1,
    "skipped": 0,
    "failed": 0
  },
  "hits": {
    "total": {
      "value": 1,
      "relation": "eq"
    },
    "max_score": 0.87546873,
    "hits": [
      {
        "_index": "tests",
        "_type": "_doc",
        "_id": "1",
        "_score": 0.87546873,
        "_source": {
          "name": "red yellow"
        }
      }
    ]
  }
}

Вывод не будет включать green yellow. Это связано с тем, что второй документ соответствует только 1/3 условий запроса, что ниже 75%

1 голос
/ 03 апреля 2020

Сначала вы должны объявить свое поле как fielddata : true, чтобы выполнить на нем скрипт:

PUT test
{
  "mappings": {
    "properties": {
      "name": {
        "type": "text",
        "fielddata": true
      }
    }
  }
}

Затем вы можете отфильтровать результаты с помощью скрипта по вашему запросу:

POST test/_search
{
  "query": {
    "bool": {
      "filter": {
        "script": {
          "script": {
            "source": """
                boolean res = true;
                for (item in doc['name']) {
                   res = 'red brown yellow'.contains(item) && res;
                 }
                 return res;
              """,
            "lang": "painless"
          }
        }
      },
      "must": [
        {
          "match": {
            "name": "red brown yellow"
          }
        }
      ]
    }
  }
}

Обратите внимание, что данные поля в текстовом поле могут стоить много, и лучше, если вы можете индексировать это поле как ключевое слово в массиве следующим образом:

1: { "name": ["red","yellow"] }
2: { "name": ["green", "yellow"] }

Запрос на поиск может быть точно таким же

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...