Период поиска и разделенные дефисом поля в Elasticsearch - PullRequest
0 голосов
/ 20 ноября 2018

Я пытаюсь найти способ использовать Elasticsearch для запроса поля, разделенного точками и дефисами.

У меня есть такой набор данных (MySQL) (используя SQLAlchemy для доступа к нему)):

id    text        tag
====================================
1     some-text   A.B.c3
2     more. text  A.B-C.c4
3     even more.  B.A-32.D-24.f9

Основная причина, по которой я в первую очередь использую ES для поиска, заключается в том, что я хочу выполнить запрос к полю text.Эта часть работает потрясающе!

Но, (я думаю) я хочу, чтобы символ tag отображался в инвертированном индексе следующим образом (я, вероятно, не буду учитывать регистр, просто включив его для иллюстрации):

A.B.c3            1
A.B-C.c4          2
B.A-C2.D-24.f9    3

Затем я хочу выполнить поиск в поле tag следующим образом:

{ "query": {
      "prefix" : { "tag" : "A.B" }
    }
}

И получить запрос, возвращающий id / строки / документы 1 и 2.

В основномЯ хочу, чтобы запрос соответствовал индексам в этой таблице истинности:

"A." = 1, 2
"A-" = 3

Как мне выполнить совпадение "A." в начале, провести различие между точкой и дефисом (возможно, повысить это), и сопоставлять среднюю фразу на основе тех же разделителей?

Я бы также хотел, чтобы эти совпадения были выше, если они возможны в начале поля tag.

Как мне это сделать, или Elasticsearch не подходит для работы?Похоже, что Elasticsearch отлично работает для моих сравнений текстовых полей в английском тексте с нормальным разделением, но поиск по тегам кажется намного сложнее.

ОБНОВЛЕНИЕ: Кажется, что когда я индексирую толькоподмножество данных, которые мои поиски возвращают результаты, которые я ожидаю, но при запросе полного набора данных, я получаю меньше обращений.

Ответы [ 2 ]

0 голосов
/ 22 ноября 2018

Это можно сделать с помощью N-Gram токенизатора.

Исходя из того, что вы указали в вопросе, я создал соответствующее сопоставление, документы и пример запроса, чтобы дать вам то, что вы ищете.

Отображение

PUT idtesttag
{
  "settings": {
    "analysis": {
      "analyzer": {
        "my_analyzer": {
          "tokenizer": "my_tokenizer"
        }
      },
      "tokenizer": {
        "my_tokenizer": {
          "type": "ngram",
          "min_gram": 2,
          "max_gram": 5
        }
      }
    }
  },
  "mappings": {
    "mydocs": {
      "properties": {
        "id": {
          "type": "long"
        },
        "text": {
          "type": "text",
          "analyzer": "my_analyzer"
        },
        "tag": {
          "type": "text",
          "analyzer": "my_analyzer"
        }
      }
    }
  }
}

Что бы это сделать, если у вас есть документ с id = 1, имеющий тег A.B, он будет хранить следующую группу символов в своем инвертированном индексе.

 A. -> 1
 .B -> 1
A.B -> 1

Таким образом, если в вашем запросе есть любое из этих трех слов, ваш документ с id=1 будет возвращен.

Образцы документов

POST idtesttag/mydocs/1
{
  "id": 1,
  "text": "some-text",
  "tag": "A.B.c3"
}

POST idtesttag/mydocs/2
{
  "id": 2,
  "text": "more. text",
  "tag": "A.B-C.c4"
}

POST idtesttag/mydocs/3
{
  "id": 3,
  "text": "even more.",
  "tag": "B.A-32.D-24.f9"
}

POST idtesttag/mydocs/4
{
  "id": 3,
  "text": "even more.",
  "tag": "B.A.B-32.D-24.f9"
}

Образец запроса

POST idtesttag/_search
{
  "query": {
    "match": {
      "tag": "A.B"
    }
  }
}

Ответ на запрос

{
  "took": 139,
  "timed_out": false,
  "_shards": {
    "total": 5,
    "successful": 5,
    "skipped": 0,
    "failed": 0
  },
  "hits": {
    "total": 3,
    "max_score": 0.8630463,
    "hits": [
      {
        "_index": "idtesttag",
        "_type": "mydocs",
        "_id": "1",
        "_score": 0.8630463,
        "_source": {
          "id": 1,
          "text": "some-text",
          "tag": "A.B.c3"
        }
      },
      {
        "_index": "idtesttag",
        "_type": "mydocs",
        "_id": "2",
        "_score": 0.66078395,
        "_source": {
          "id": 2,
          "text": "more. text",
          "tag": "A.B-C.c4"
        }
      },
      {
        "_index": "idtesttag",
        "_type": "mydocs",
        "_id": "4",
        "_score": 0.46659434,
        "_source": {
          "id": 3,
          "text": "even more.",
          "tag": "B.A.B-32.D-24.f9"
        }
      }
    ]
  }
}

Обратите внимание, что документы 1, 2 и 4 возвращаютсяв ответ.document 4 - это совпадение в середине предложения , тогда как документы 1 & 2 находятся в начале.

Также обратите внимание на значение оценки, как оно выглядит.

Повышение на основе hypen

Теперь что касается повышения на основе символа hypen, я бы предложил вам запрос Bool вместе с Regex Queryс бустингом .Ниже приведен пример запроса, который я придумал.

Обратите внимание, что просто для простоты я добавил регулярное выражение, где оно будет только увеличиваться, если hypen будет рядом с A.B.

POST idtesttag/_search
{
  "query": {
    "bool": {
      "must" : {
        "match" : { "tag" : "A.B" }
      },
      "should": [
        {
          "regexp": {
            "tag": {
              "value": "A.B-.*",
              "boost": 3
            }
          }
        }
      ]
    }
  }
}

Повышение ответа на запрос

{
  "took": 2,
  "timed_out": false,
  "_shards": {
    "total": 5,
    "successful": 5,
    "skipped": 0,
    "failed": 0
  },
  "hits": {
    "total": 3,
    "max_score": 3.660784,
    "hits": [
      {
        "_index": "idtesttag",
        "_type": "mydocs",
        "_id": "2",
        "_score": 3.660784,
        "_source": {
          "id": 2,
          "text": "more. text",
          "tag": "A.B-C.c4"
        }
      },
      {
        "_index": "idtesttag",
        "_type": "mydocs",
        "_id": "4",
        "_score": 3.4665942,
        "_source": {
          "id": 3,
          "text": "even more.",
          "tag": "B.A.B-32.D-24.f9"
        }
      },
      {
        "_index": "idtesttag",
        "_type": "mydocs",
        "_id": "1",
        "_score": 0.8630463,
        "_source": {
          "id": 1,
          "text": "some-text",
          "tag": "A.B.c3"
        }
      }
    ]
  }
}

Просто убедитесь, что ваше тестирование является тщательным, когда речь идет о повышении, потому что все это влияет на оценку, и убедитесь, что вы делаете это с введенными данными prodв DEV / TEST Упругий индекс.

Таким образом, вы не будете бояться, когда увидите совершенно разные результаты, если перейдете в PROD Elastic.

Извините, это довольно длинный ответ, но я надеюсь, что это поможет!

0 голосов
/ 22 ноября 2018

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

ТогдаЯ хочу найти поле тега следующим образом:

На основании того, что вы описали в своем посте рег.поле 'tag', вот мои 2 цента.

Ваши данные Mysql должны быть одного типа (в 6.5 это «doc» по умолчанию).Тем не менее, вам необходимо явно определить отображение индекса - особенно в поле «тег», поскольку у вас, похоже, есть требования для поиска.

Я бы определил ваше поле «тег» как мультиполе:

  • введите «ключевое слово» для агрегатов
  • введите «текст» для поиска с помощью специального анализатора (который может использовать токенайзер «пробельные символы» и фильтр маркеров «ребро ngram»

(если вам не нужны агрегации, просто определите текстовое поле типа с помощью пользовательского анализатора)

FYI, Analyze API покажет вам, что ES делает с вашими «теговыми» данными, и поможет вам определить соответствие, соответствующее вашим требованиям.

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