ElasticSearch — подробное объяснение операторов запроса

Elasticsearch

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

Если вы не знаете es, рекомендуется сначала прочитать основные понятия es:nuggets.capable/post/684490…

поиск по параметру URL

Этот метод аналогичен запросу get, где параметры запроса склеиваются со ссылкой, напримерGET /school/student/_search?参数, несколько параметров разделяются знаком &

запросить все

Заказ:GET /school/student/_search

возвращение:

{
  "took": 7, //查询耗时,毫秒
  "timed_out": false, //是否超时,timeout 不是停止执行查询,它仅仅是告知正在协调的节点返回到目前为止收集的结果并且关闭连接
  "_shards": {
    "total": 5, //请求的分片数量,索引拆成了5个分片,所以对于搜索请求,会打到所有的primary shard
    "successful": 5,
    "skipped": 0,
    "failed": 0
  },
  "hits": {
    "total": 2, //符合条件的总条数,这里查的是所有
    "max_score": 1, //匹配分数
    "hits": [ //数据
      {
        "_index": "school",
        "_type": "student",
        "_id": "2",
        "_score": 1,
        "_source": {
          "name": "houyi",
          "age": 23,
          "class": 2,
          "gender": "男"
        }
      },
      {
        "_index": "school",
        "_type": "student",
        "_id": "1",
        "_score": 1,
        "_source": {
          "name": "吕布",
          "age": 21,
          "class": 2,
          "gender": "男"
        }
      }
    ]
  }
}

Многоиндексный, многотипный поиск

Укажите специальный индекс и введите URL-адрес для многоиндексного и многотипного поиска.

  1. /_search: Поиск всех типов во всех индексах
  2. /school/_search:существуетschoolИскать все типы в индексе
  3. /school,ad/_search:существуетschoolиadИскать все типы в индексе
  4. /s*,a*/_search: в целомgиaвсе типы в индексе, начиная с
  5. /school/student/_search:существуетschoolПоиск в индексеstudentтип
  6. /school,ad/student,phone/_search:существуетschoolиadпоиск по индексуstudentиphoneтип
  7. /_all/student,phone/_search: поиск по всем индексамstudentиphoneтип

Запрос по условию

Заказ:GET /school/student/_search?q=name:houyi

Запросить записи, чье имя houyi

Дополнительные параметры запроса:

Запрос DSL

Elasticsearch предоставляет полный DSL запросов на основе JSON для определения запросов. DSL имеет набор компонентов запроса, которые можно сопоставлять в бесконечных комбинациях для создания различных сложных запросов.

заявление листа

Оператор листа: как и оператор соответствия, он используется для сравнения строки запроса с полем или полями (одно условие). Например:

   GET /ad/phone/_search
   {
     "query": {
       "match": {
         "name": "phone"
       }
     }
   }

Составной запрос

Пользователь объединяет другие операторы запроса, такие какboolоператор, позволяющий комбинировать другие операторы по мере необходимости, в том числеmust,must_not,shouldиfilterЗаявление (запрос комбинации нескольких условий) Например:

GET /ad/phone/_search
{
  "query": {
    "bool": {
      "must": [
        {"match": {
          "name": "phone"
        }}
      ]
      , "must_not": [
        {"match": {
          "color": "red"
        }}
      ]
      , "should": [
        {"match": {
          "price": 5000
        }}
      ]
      , "filter": {
          "term": {
            "label": "phone"
          }
      }
    }
  }
}

must: указывает, что документ должен содержать содержимое запроса

must_not: указывает, что документ не должен содержать содержимое запроса

should: Указывает, что оценка релевантности документа может быть увеличена, если документ соответствует

На самом деле мы можем использовать два структурированных оператора: Структурированные запросы.query DSLи структурированная фильтрацияFilter DSL

  1. структурированный запросquery DSL

    Он используется для проверки соответствия содержимого условиям. Предложения bool и match, используемые в запросе содержимого, используются для расчета оценки соответствия каждого документа. Метаполе _score указывает степень соответствия. Структура запроса начинается с параметра запроса для выполнения запроса содержимого.

  2. структурированная фильтрацияFilter DSL

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

    Использование фильтров запросов будет автоматически кэшироваться es для повышения эффективности.

В принципе, при использовании оператора запроса для полнотекстового поиска или другой оценки релевантности используйте операторы фильтра для остальных.

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

PUT /ad/phone/1
{
  "name":"phone 8",
  "price": 6000,
  "color":"white",
  "ad":"this is a white phone",
  "label":["white","nice"]
}

PUT /ad/phone/2
{
  "name":"xiaomi 8",
  "price": 4000,
  "color":"red",
  "ad":"this is a red phone",
  "label":["white","xiaomi"]
}

PUT /ad/phone/3
{
  "name":"huawei p30",
  "price": 5000,
  "color":"white",
  "ad":"this is a white phone",
  "label":["white","huawei"]
}

Пример запроса

1. Получить все

GET /ad/phone/_search
{
  "query": {
    "match_all": {}
  }
}

match_allСопоставьте все данные и верните метаполе в результат_scoreоценка 1

2. Пейджинговый запрос, начиная со второго, отмечаем два (не использоватьfrom,sizeДля глубокого пейджинга будут проблемы с производительностью)

GET /ad/phone/_search
{
  "query": {
    "match_all": {}
  },
  "from": 1,
  "size": 2
}

Если этот метод разбиения на страницы выполняет глубокое разбиение по страницам, например, на 100 страниц с десятью фрагментами данных на странице, он будет запрашивать 100 * 10 фрагментов данных из каждого сегмента. Предположим, что имеется пять сегментов, то есть 5000 фрагментов данных, и затем сохранить их в памяти.Отсортировать по порядку, а затем вернуть 1000-1010-е данные в коллекции после взятия последовательности

3. Укажите поля, возвращаемые запрошенными данными.

GET /ad/phone/_search
{
  "query": {
    "match_all": {}
  },
  "_source": ["name","price"]
}

В возвращаемых данных только returnnameиpriceполе

4. Поле объявления содержит слово белый

GET /ad/phone/_search
{
  "query": {
    "match": {
      "ad": "white"
    }
  }
}

Метаполя в возвращаемом результате_scoreЕсть рейтинги, инструкция по применениюqueryоценка будет рассчитана

5. Поле объявления содержит слово белый и отсортировано по цене в порядке возрастания

GET /ad/phone/_search
{
  "query": {
    "match": {
      "ad": "white"
    }
  }, 
  "sort": [
    {
      "price": {
        "order": "asc"
      }
    }
  ]
}

6. Поле цены больше 5000

GET /ad/phone/_search
{
  "query": {
    "bool": {
      "filter": {
        "range": {
          "price": {
            "gt": 5000
          }
        }
      }
    }
  }
}

Метаполя в возвращаемом результате_scoreПоле равно 0, нет баллов, что указывает на использованиеfilterРейтинг не будет рассчитываться

7. Поле объявления содержит слово белый, а поле цены больше 5000

GET /ad/phone/_search
{
  "query": {
    "bool": {
      "must": [
        {
          "match": {
            "ad": "white"
          }
        }
      ], 
      "filter": {
        "range": {
          "price": {
            "gt": 5000
          }
        }
      }
    }
  }
}

8. Запросnameполе содержит словаphoneколичество документов

GET /ad/phone/_count
{
  "query": {
    "match": {
      "name": "phone"
    }
  }
}

Подробное объяснение ключевых слов

1. match_allЗапрос

Запрос просто соответствует всем документам

GET /ad/phone/_search
{
  "query": {
    "match_all": {}
  }
}

2. matchЗапрос

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

Полнотекстовый поиск:

GET /ad/phone/_search
{
  "query": {
    "match": {
      "ad": "a red"
    }
  }
}

Полнотекстовый поиск сначала выполнит сегментацию слов в строке запроса.a redбудет разделен наaиred, а затем сопоставить в инвертированном индексе, поэтому этот оператор найдет все три документа

Точный запрос:

GET /ad/phone/_search
{
  "query": {
    "match": {
      "price": "6000"
    }
  }
}

Для запросов с точным значением вместо запроса можно использовать оператор фильтра, поскольку фильтр будет кэшироваться.

operatorработать:

matchТакже принимаются запросыoperatorоператор в качестве входного параметра, по умолчанию операторor. мы можем изменить его наandсделать так, чтобы все указанные термины совпадали

GET /ad/phone/_search
{
  "query": {
    "match": {
      "ad": {
        "query": "a red",
        "operator": "and"
      }
    }
  }
}

Точное совпадение:

matchПоддержка запросовminimum_should_matchПараметр минимального соответствия может указывать количество терминов, которые должны сопоставляться, чтобы указать, связан ли документ. Мы можем установить его на конкретное число (имеется в виду количество слов, которые должны соответствовать инвертированному индексу), чаще устанавливается в процентах, потому что мы не можем контролировать количество слов, которые пользователи вводят при поиске.

GET /ad/phone/_search
{
  "query": {
    "match": {
      "ad": {
        "query": "a red",
        "minimum_should_match": "2"
      }
    }
  }
}

будет возвращать только совпаденияaиredДокумент из двух слов возвращается, еслиminimum_should_matchравен 1, то пока одно из слов совпадает, документ будет возвращен

3. multi_matchЗапрос

Запрос с несколькими полями, например запросcolorиadполе содержит словаredдокументация

GET /ad/phone/_search
{
  "query": {
    "multi_match": {
      "query": "red",
      "fields": ["color","ad"]
    }
  }
}

4. rangeЗапрос

Запрос диапазона, запрос документов, цена которых больше 4000 и меньше 6000

GET /ad/phone/_search
{
  "query": {
    "range": {
      "price": {
        "gt": 4000,
        "lt": 6000
      }
    }
  }
}

Оператор запроса диапазона:gt(больше, чем),gte(больше или равно),lt(меньше, чем),lte(меньше или равно);

5. termЗапрос

Запрос точного значения

ЗапросpriceДокументы с полями, равными 6000

GET /ad/phone/_search
{
  "query": {
    "term": {
      "price": {
        "value": "6000"
      }
    }
  }
}

Запросnameполе равноphone 8документация

GET /ad/phone/_search
{
  "query": {
    "term": {
      "name": {
        "value": "phone 8"
      }
    }
  }
}

Возвращаемое значение выглядит следующим образом, имя не запрашиваетсяphone 8документация

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

почему не нашелphone 8Этот документ должен быть представлен здесьtermПринцип запроса

termЗапрос пойдет к инвертированному индексу, чтобы найти точныйterm, он не попадет в токенизатор, будет соответствовать только инвертированному индексу, иnameполеtypeтипtext, выполнит сегментацию слов, будетphone 8разделен наphoneи8,Мы используемtermЗапросphone 8не в инвертированном индексеphone 8, поэтому не было запрошено ни одного совпадающего документа

termзапрос сmatchразница запросов

  • termПри запросе не будет сегментации слов, а инвертированный индекс будет сопоставляться напрямую
  • matchСегментация слов будет выполняться при запросе, запросphone 8, сначала будет причастием вphoneи8, а затем соответствовать инвертированному индексу, поэтому результат будетphone 8иxiaomi 8Оба документа найдены.

Следует отметить еще одну вещь, посколькуtermЗапрос не будет проходить через токенизатор, а вернется к совпадению с инвертированным индексом, поэтому структура запроса связана с тем, как токенизатор разделяет слова, например, добавляет новое./ad/phoneдокумент под типом,nameполе назначается какOppo, затем используйтеtermЗапросOppoДокумент не будет запрошен, так как по умолчанию используется es.standardTokenizer, который преобразует слова в строчные буквы после токенизации, поэтому используйтеoppoНе могу найти документацию, используйте строчные буквыoppoможно найти

GET /ad/phone/_search
{
  "query": {
    "term": {
      "name": {
        "value": "Oppo" //改成oppo可以查出新添加的文档
      }
    }
  }
}

Это не значит, что вы понимаетеstandardтокенизатор, но чтобы получить все какtermЭтот тип результата запроса связан с выбранным токенизатором. Понимание выбранного токенизатора поможет нам написать операторы запроса.

6. termsЗапрос

termsзапрос сtermТо же, что запрос, но позволяет указать, сколько совпадений должно совпадать.Если поле содержит какое-либо из указанных значений, то документ удовлетворяет условию

GET /ad/phone/_search
{
  "query": {
    "terms": {
      "ad": ["red","blue"]
    }
  }
}

7. existsзапрос иmissingЗапрос

Используется для поиска этих значений в указанном поле (exists) или без значения (missing) документация

уточнитьnameПоля имеют значения:

GET /ad/phone/_search
{
  "query": {
    "bool": {
      "filter": {
        "exists": {
          "field": "name"
        }
      }
    }
  }
}

уточнитьnameПоле не имеет значения:

GET /ad/phone/_search
{
  "query": {
    "bool": {
      "filter": {
        "missing": {
          "field": "name"
        }
      }
    }
  }
}

8. match_phraseЗапрос

Фразовый запрос, точное соответствие, запросa redбудет соответствоватьadполе содержитa redФраза без запроса сегментации слов и не будет содержать запросa 其他词 redтакой документ

GET /ad/phone/_search
{
  "query": {
    "match_phrase": {
      "ad": "a red"
    }
  }
}

9. scrollЗапрос

Подобно пейджинговому запросу, он не поддерживает запрос перехода на страницу и может запрашивать только одну страницу за раз.scrollЗапросы предназначены не для пользовательских запросов в реальном времени, а для обработки больших объемов данных, например, для переиндексации содержимого одного индекса в новый индекс с другой конфигурацией.

POST /ad/phone/_search?scroll=1m
{
  "query": {
    "match_all": {}
  },
  "size": 1,
  "from": 0
}

Возвращаемое значение содержит"_scroll_id": "DnF1ZXJ5VGhlbkZldGNoBQAAAAAAAAAQFlV6T3VqY2NaVDBLRG5uZXdiZ0hFYUEAAAAAAAAAERZVek91amNjWlQwS0RubmV3YmdIRWFBAAAAAAAAABIWVXpPdWpjY1pUMEtEbm5ld2JnSEVhQQAAAAAAAAATFlV6T3VqY2NaVDBLRG5uZXdiZ0hFYUEAAAAAAAAAFBZVek91amNjWlQwS0RubmV3YmdIRWFB"

Используйте его в следующем запросе_scroll_idВы можете запросить документы на следующей странице

POST /_search/scroll 
{
    "scroll" : "1m", 
    "scroll_id" : "DnF1ZXJ5VGhlbkZldGNoBQAAAAAAAAAYFlV6T3VqY2NaVDBLRG5uZXdiZ0hFYUEAAAAAAAAAGRZVek91amNjWlQwS0RubmV3YmdIRWFBAAAAAAAAABYWVXpPdWpjY1pUMEtEbm5ld2JnSEVhQQAAAAAAAAAXFlV6T3VqY2NaVDBLRG5uZXdiZ0hFYUEAAAAAAAAAFRZVek91amNjWlQwS0RubmV3YmdIRWFB" 
}

10. multi getЗапрос

Позволяет извлекать несколько документов на основе индекса, типа (необязательно) и идентификатора (и, возможно, маршрута), включая информацию об ошибке в ответ, если документ не может быть извлечен

```json
GET /ad/phone/_mget
{
  "ids": ["1","8"]
}
```

11. bulkМассовые операции

bulkМассовые операции могут реализовывать несколько документов в одном вызове API.create,index,updateилиdelete. Это может значительно повысить скорость индексации.

bulkТело запроса выглядит следующим образом

{ action: { metadata }}\n 
{ request body        }\n
{ action: { metadata }}\n
{ request body        }\n
...

actionДолжен быть одним из следующих:

поведение объяснять
create Создается, когда документ не существует
index Создайте новый документ или замените существующий документ
update Частично обновить документацию
delete удалить документ

Документы необходимо указывать при индексировании, создании, обновлении или удалении_index,_type,_idЭти метаданные (metadata)

пример:

    PUT _bulk
    { "create" : { "_index" : "ad", "_type" : "phone", "_id" : "6" }}
    { "doc" : {"name" : "bulk"}}
    { "index" : { "_index" : "ad", "_type" : "phone", "_id" : "6" }}
    { "doc" : {"name" : "bulk"}}
    { "delete":{  "_index" : "ad", "_type" : "phone", "_id" : "1"}}
    { "update":{  "_index" : "ad", "_type" : "phone", "_id" : "3"}}
    { "doc" : {"name" : "huawei p20"}}

возвращение:

    {
      "took": 137,
      "errors": true, //如果任意一个文档出错,这里返回true,
      "items": [ //items数组,它罗列了每一个请求的结果,结果的顺序与我们请求的顺序相同
        {
          //create这个文档已经存在,所以异常
          "create": { 
            "_index": "ad",
            "_type": "phone",
            "_id": "6",
            "status": 409,
            "error": {
              "type": "version_conflict_engine_exception",
              "reason": "[phone][6]: version conflict, document already exists (current version [2])",
              "index_uuid": "9F5FHqgISYOra_P09HReVQ",
              "shard": "2",
              "index": "ad"
            }
          }
        },
        {
          //index这个文档已经存在,会覆盖
          "index": { 
            "_index": "ad",
            "_type": "phone",
            "_id": "6",
            "_version": 3,
            "result": "updated",
            "_shards": {
              "total": 2,
              "successful": 1,
              "failed": 0
            },
            "_seq_no": 6,
            "_primary_term": 5,
            "status": 200
          }
        },
        {
          //删除  
          "delete": { 
            "_index": "ad",
            "_type": "phone",
            "_id": "1",
            "_version": 1,
            "result": "not_found",
            "_shards": {
              "total": 2,
              "successful": 1,
              "failed": 0
            },
            "_seq_no": 4,
            "_primary_term": 5,
            "status": 404
          }
        },
        {
          //修改  
          "update": { 
            "_index": "ad",
            "_type": "phone",
            "_id": "3",
            "_version": 3,
            "result": "noop",
            "_shards": {
              "total": 2,
              "successful": 1,
              "failed": 0
            },
            "status": 200
          }
        }
      ]
    }

bulkЗапросы не являются атомарными операциями, они не могут реализовывать транзакции. Каждый запрос обрабатывается отдельно, поэтому успех каждого запроса не мешает другим операциям.

12. fuzzyЗапрос

нечеткий запрос,fuzzyЗапрос вычисляет сходство написания с ключевым словом

    GET /ad/phone/_search
    {
      "query": {
        "fuzzy": {
          "color":{
            "value": "res"
            , "fuzziness": 2,
            "prefix_length": 1
          }
        }
      }
    }

настройки параметров:

fuzziness: максимальное расстояние редактирования, по умолчаниюAUTO

prefix_length: начальное количество символов, которые не будут «затенены». Это помогает уменьшить количество терминов, которые необходимо проверить, по умолчанию0

max_expansions:fuzzyМаксимальное количество терминов, до которых будет расширяться запрос. По умолчанию50, установите значение small, чтобы оптимизировать запросы

transpositions: Поддерживается ли нечеткое транспонирование (abba), значение по умолчаниюfalse

13. wildcardЗапрос

Нечеткие запросы, поддерживающие подстановочные знаки, ? соответствует одному символу, * соответствует любому символу

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

    GET /ad/phone/_search
    {
      "query": {
        "wildcard": {
          "color": "r?d"
        }
      }
    }

Продолжение следует...