• elasticsearch (dsl)


    正排索引 和 倒排索引

    正排索引:通过id ,查询content

    倒排索引:通过content,查询到符合的 ids

    eg:

    正排索引就是通过《静夜思》,找到整片文章。

    倒排索引通过“明月”,找到《静夜思》 《望月怀古》《关山月》等

    get 查询

    索引的基本信息:

    GET your_index/_mapping  //跟看mysql表字段差不多,可以查看字段的类型type:keyword,text
    GET your_index/_alias  //查看索引的别名
    GET /_cat/health?v  //查看集群状态
    GET _cat/indices // 查看所有index
    GET _cat/shards/your_index  //查看指定索引的分片数,每个分片有主(p)副(r)分片

    查询索引内容:

    match_all

    1. GET /you_index/_search
    2. {
    3. "query":{
    4. "match_all": {}
    5. }

    bool 

    bool查询是一个非常强大且常用的复合查询,它允许你组合多个查询条件。bool 查询的核心概念包括以下四种子句:

    1. must: 子句必须匹配文档。类似于 SQL 中的 AND 操作符。
    2. filter: 子句必须匹配文档,但不影响评分。也就是说,它只过滤文档,但不参与评分计算。
    3. should: 子句可以匹配文档。如果在一个 bool 查询中包含了多个 should 子句,则至少一个 should 子句必须匹配文档。类似于 SQL 中的 OR 操作符。
    4. must_not: 子句不能匹配文档。类似于 SQL 中的 NOT 操作符。

    eg: 

    1. GET you_index/_search
    2. {
    3. "query": {
    4. "bool": {
    5. "must": [
    6. {
    7. "bool": {
    8. "should": [
    9. {
    10. "term": {
    11. "name": {
    12. "value": "林俊凯",
    13. "boost": 1
    14. }
    15. }
    16. },
    17. {
    18. "term": {
    19. "zh_name": {
    20. "value": "林俊凯",
    21. "boost": 1
    22. }
    23. }
    24. }
    25. ]
    26. }
    27. },
    28. {
    29. "bool": {
    30. "should": [
    31. {
    32. "range": {
    33. "fans_num": {
    34. "gte": "800"
    35. }
    36. }
    37. },
    38. {
    39. "terms": {
    40. "tag": [
    41. 1010,
    42. 1013
    43. ]
    44. }
    45. }
    46. ]
    47. }
    48. }
    49. ]
    50. }
    51. },
    52. "sort": {
    53. "_score": {
    54. "order": "desc"
    55. },
    56. "score": {
    57. "order": "desc"
    58. }
    59. }
    60. }

    range

    1. "range": {
    2. "fans_num": {
    3. "gte": 800,
    4. "lte":126334
    5. }
    6. }

    gte:大于等于;lte小于等于

    term 

     不分词,精准完全匹配查询

    1. GET your_index_search/_search
    2. {
    3. "query": {
    4. "term": {
    5. "name": {
    6. "value": "天空"
    7. }
    8. }
    9. }
    10. }

    terms

    不分词,命中数组一个即可,不要求全部命中

    1. GET your_index_search/_search
    2. {
    3. "query": {
    4. "terms": {
    5. "tag": [
    6. "美食",
    7. "购物"
    8. ]
    9. }
    10. }
    11. }

    prefix

    前缀匹配,不分词 ,精准匹配前半部分

    1. GET your_index_search/_search
    2. {
    3. "query": {
    4. "prefix": {
    5. "name_full": {
    6. "value": "林俊"
    7. }
    8. }
    9. }
    10. }

    林俊凯,林俊xxx都会命中

    multi_match

    会对query词进行分词

    1. GET your_index_search/_search
    2. {
    3. "query": {
    4. "bool": {
    5. "must": [
    6. {
    7. "multi_match": {
    8. "query": "北京景点",
    9. "fields": [
    10. "name",
    11. "name_full",
    12. "name_lower"
    13. ],
    14. "analyzer":"ik",
    15. "minimum_should_match":"3<80%"
    16. }
    17. }
    18. ]
    19. }
    20. }
    21. }

    1. 这里的 "minimum_should_match": "3<80%" 指定了如下规则:

    • 如果分词数量小于或等于 3,则必须匹配所有分词。

    • 如果分词数量大于 3,则至少匹配 80% 的分词。

    2. 这里的“analyzer”,是分词器,常见的有ik ik-smart  standard mla 

    1. GET _analyze
    2. {
    3. "analyzer":"mla",
    4. "text":"北京景点"
    5. }
    6. //结果为
    7. {
    8. "tokens": [
    9. {
    10. "token": "北京",
    11. "start_offset": 0,
    12. "end_offset": 2,
    13. "type": "CN_WORD",
    14. "position": 0
    15. },
    16. {
    17. "token": "景点",
    18. "start_offset": 2,
    19. "end_offset": 4,
    20. "type": "CN_WORD",
    21. "position": 1
    22. }
    23. ]
    24. }

    3.多个字段上查找,best_fields 表示从所有指定的字段中选择匹配度最高的字段来计算得分.

    1. {
    2. "multi_match": {
    3. "query": "灵岩景区",
    4. "fields": [
    5. "title^1.0",
    6. "content^1.0",
    7. ],
    8. "type": "best_fields",
    9. "operator": "AND",
    10. "analyzer": "mla",
    11. "slop": 0,
    12. "prefix_length": 0,
    13. "max_expansions": 50,
    14. "lenient": false,
    15. "zero_terms_query": "NONE",
    16. "boost": 1
    17. }
    18. }

    eg:“北京景点”分词为【北京,景点】,分词项为2,小于3,那么【北京】和【景点】需要在field中匹配到。multi_match 查询的目的是在多个字段中搜索查询词中的词语,并且匹配规则会跨字段应用,比如 【北京】在name匹配到,【景点】在name_lower配到到,即匹配成功。

    注意⚠️:纯英文的按照空格 分词!!!!

    match

    会分词,multi_match会涉及多个字段的作用域。match只涉及一个field。 query = 灵岩景区,通过分词为 "灵岩""景区"。

    operator 作用:

    • 如果 "operator": "AND",则文档中必须同时包含 "灵岩""景区",才会被匹配到。即两个词必须都存在。

    • 如果 "operator": "OR"(默认设置),则文档中只要包含 "灵岩""景区" 其中一个词,就会被匹配到。这是更宽松的匹配条件。

    1. $match = new \Elastica\Query\Match();
    2. $match->setField("name", array(
    3. "query" => strtolower($params['keyword']),
    4. "fuzziness" => "AUTO",
    5. "operator" => "or",
    6. "analyzer" => "ik_max_word"
    7. ));

    multi_phrase

    会对query词进行分词(有的人会认为不会分词,❌),match_phrase要求严格,不仅要求,能够匹配到分词后的所有单词,且分词后的单词顺序也要和命中结果中的顺序保持一致。

    1. GET your_index_search/_search
    2. {
    3. "query": {
    4. "bool": {
    5. "must": [
    6. {
    7. "match_phrase": {
    8. "name": "孤独的战士"
    9. }
    10. }
    11. ]
    12. }
    13. }
    14. }

    name = “孤独的战士” 通过ik_max_word 分词后 【孤独的,孤独,战士】,es中有个name = “孤独星球的战士”是否能被召回呢? 看一下分词:【孤独,星球,战士】。“孤独的”未被匹配到,所以不会被召回。

    假如,name = “孤独的战士”的分词为【孤独,战士】,能否召回“孤独星球的战士”呢?可以!通过设置slop,最大间隔数,默认是0。

    为什么match能找到,term查询不到呢?

    首先,要看创建索引的时候mapping ,字段的类型。如果是type是keyword,不允许分词。

    其次,查看字段类型发现是text,term查询的字段类型只能是keyword

    1. "keyword_full": {
    2. "type": "text",
    3. "fields": {
    4. "keyword": {
    5. "type": "keyword"
    6. }
    7. }
    8. },

    如果想要查询到想要的文档结果,会有很多因素。首先,用的什么分词器(ik_max_word,ik_smart),分成的tokens决定了匹配度。其次,就是dsl,精准查询就用term ,

    最后,写一个例子,多路召回,尽可能多的结果。

  • 相关阅读:
    AI模型精确解析果蝇行为,未来或可预测人类行为
    ESP32 Arduino实战协议篇-搭建独立的 Web 服务器
    高性能零售IT系统的建设07-通过一次重大危机感受Redis从使用到失智到理性的治理
    可以二次开发的 数据治理系统
    代码没有报错但是运行的时候没反应是怎么回事
    利用 python 脚本 PyRdp 设置 RDS 服务器蜜罐 Honeypot
    深入理解计算机系统学习笔记
    ubuntu22.04下hadoop3.3.6+hbase2.5.6+phoenix5.1.3开发环境搭建
    leetcode31. 下一个排列python_双指针(思想太美妙)
    LeetBook 刷题笔记:链表(三)
  • 原文地址:https://blog.csdn.net/qq_35720068/article/details/139356755