• Elasticsearch6实践


    目录

    一、列表搜索

    1、需求

    2、ES索引设计

    3、页面搜索条件

    4、ES的分页搜索DSL语句

    5、Tip

    二、聚合搜索

    1、需求

    2、DSL查询语句

    3、查询结果

    三、随机排序

    1、需求

    2、DSL查询语句


    一、列表搜索

    1、需求

        公告列表,需要支持以下搜索

    • 根据文本输入,模糊搜索公告标题和公告正文。
    • 支持公告类型搜索,单选
    • 支持根据公告所在省市区搜索,可多选。如,可以同时选中“浙江”,“广州”,“朝阳区”
    • 支持公告包含的行业搜索,行业包括一级行业、二级行业,可多选。
    • 支持公告发布的时间搜索,如最近7天,最近一个月,或选定一段日期范围。
    • 支持根据公告中涉及到的金额范围搜索,如1万-10万,10万-200万,200万-500万,可选择多个范围

    2、ES索引设计

    1. {
    2. "aliases":{
    3. "announcement_index_read":{
    4. },
    5. "announcement_index_write":{
    6. }
    7. },
    8. "settings":{
    9. "index":{
    10. "sort.field":"createTime", //默认根据公告发布时间排序
    11. "sort.order":"desc"
    12. },
    13. "analysis":{
    14. "analyzer":{
    15. "ik_max_word_ignore_html":{
    16. "type":"custom",
    17. "char_filter":[
    18. "html_strip"
    19. ],
    20. "tokenizer":"ik_max_word"
    21. },
    22. "comma":{
    23. "type":"pattern",
    24. "pattern":","
    25. }
    26. },
    27. "char_filter":{
    28. "html_char_filter":{
    29. "escaped_tags":[
    30. ],
    31. "type":"html_strip"
    32. }
    33. }
    34. }
    35. },
    36. "mappings":{
    37. "_doc":{
    38. "properties":{
    39. "id":{
    40. "type":"keyword"
    41. },
    42. "districtCodes":{ //省市区信息,存储省市区的code,如浙江省、杭州市、余杭区,对应存储”100,101,111",支持根据浙江省搜索到该公告,也支持根据区搜索到该公告
    43. "type":"text",
    44. "analyzer":"comma"
    45. },
    46. "annTypes":{ //公告类型,一个公告可能对应多个类型,多个类型都逗号分隔存储
    47. "type":"text",
    48. "analyzer":"comma"
    49. },
    50. "announcementId":{
    51. "type":"keyword"
    52. },
    53. "title":{ //公告标题,支持根据标题模糊搜索
    54. "type":"text",
    55. "analyzer":"ik_max_word",
    56. "search_analyzer":"ik_smart"
    57. },
    58. "createTime":{ //公告发布时间
    59. "type":"date",
    60. "format":"yyyy-MM-dd HH:mm:ss||yyyy-MM-dd||epoch_millis"
    61. },
    62. "amount":{ //公告涉及到的金额
    63. "type":"double"
    64. },
    65. "industryNames":{ //行业名称,包含所有一级行业和二级行业,多个行业用逗号分隔,如“安防,电子电器,数码产品”。支持根据行业名称模糊搜索,支持根据多个行业精确搜索。
    66. "type":"text",
    67. "fields":{
    68. "fuzzy":{
    69. "type":"text",
    70. "analyzer":"ik_max_word"
    71. },
    72. "keyword":{
    73. "type":"keyword"
    74. }
    75. },
    76. "analyzer":"comma",
    77. "search_analyzer":"ik_smart"
    78. },
    79. "industryNameJson":{ //行业信息,前端页面展示需要嵌套格式的行业信息,纯展示使用,存储一级行业、二级行业嵌套的json格式,如"[{\"firstIndustryName\":\"安防\",\"secondIndustryName\":\"安防设备\"},{\"firstIndustryName\":\"行政办公\",\"secondIndustryName\":\"办公用品\"}]"
    80. "type":"text"
    81. },
    82. "content":{ //公告正文内容,内容包含html标签,需要根据输入内容模糊搜索
    83. "type":"text",
    84. "term_vector":"with_positions_offsets",
    85. "analyzer":"ik_max_word_ignore_html",
    86. "search_analyzer":"ik_smart"
    87. }
    88. }
    89. }
    90. }
    91. }

    3、页面搜索条件

    搜索条件,公告类型=”招标公告“,行业=”安防和办公“,金额范围为100万到200万和20万到50万,发布日期为2021/03/03到2023/10/12,标题和正文内容匹配”信息化“

    1. {
    2. "annType":"招标公告",
    3. "industry":"安防,办公",
    4. "amountRange":"100#200,20#50",
    5. "districtCodes":"330000,650000",
    6. "createTimeRange":"2021/03/03#2023/10/12",
    7. "searchValue":"信息化",
    8. "sort":"desc",
    9. "curPage":1,
    10. "pageSize":10
    11. }

    4、ES的分页搜索DSL语句

        注:支持根据标题和正文内容搜索,实际是同时匹配title和content两个字段,DSL是把两个字段的查询包装在一个should中,每个字段的匹配operator默认使用or,将operator改成and后,精度变准确了。

    1. {
    2. "size":10,
    3. "query":{
    4. "bool":{
    5. "filter":[
    6. {
    7. "terms":{
    8. "annTypes":[
    9. "招标公告"
    10. ],
    11. "boost":1
    12. }
    13. },
    14. {
    15. "terms":{
    16. "districtCodes":[
    17. "330000",
    18. "650000"
    19. ],
    20. "boost":1
    21. }
    22. },
    23. {
    24. "range":{
    25. "createTime":{
    26. "include_lower":true,
    27. "include_upper":false,
    28. "from":1614700800000,
    29. "boost":1,
    30. "to":1697126399000
    31. }
    32. }
    33. },
    34. {
    35. "bool":{
    36. "adjust_pure_negative":true,
    37. "should":[
    38. {
    39. "range":{
    40. "amount":{
    41. "include_lower":true,
    42. "include_upper":true,
    43. "from":100000000,
    44. "boost":1,
    45. "to":200000000
    46. }
    47. }
    48. },
    49. {
    50. "range":{
    51. "amount":{
    52. "include_lower":true,
    53. "include_upper":true,
    54. "from":20000000,
    55. "boost":1,
    56. "to":50000000
    57. }
    58. }
    59. }
    60. ],
    61. "minimum_should_match":"1",
    62. "boost":1
    63. }
    64. },
    65. {
    66. "bool":{
    67. "adjust_pure_negative":true,
    68. "should":[
    69. {
    70. "match":{
    71. "industryNames.fuzzy":{
    72. "auto_generate_synonyms_phrase_query":true,
    73. "query":"信息化",
    74. "zero_terms_query":"NONE",
    75. "fuzzy_transpositions":true,
    76. "boost":1,
    77. "prefix_length":0,
    78. "operator":"AND",
    79. "lenient":false,
    80. "max_expansions":50
    81. }
    82. }
    83. },
    84. {
    85. "match":{
    86. "content":{
    87. "auto_generate_synonyms_phrase_query":true,
    88. "query":"信息化",
    89. "zero_terms_query":"NONE",
    90. "fuzzy_transpositions":true,
    91. "boost":1,
    92. "prefix_length":0,
    93. "operator":"AND",
    94. "lenient":false,
    95. "max_expansions":50
    96. }
    97. }
    98. },
    99. {
    100. "match":{
    101. "title":{
    102. "auto_generate_synonyms_phrase_query":true,
    103. "query":"信息化",
    104. "zero_terms_query":"NONE",
    105. "fuzzy_transpositions":true,
    106. "boost":1,
    107. "prefix_length":0,
    108. "operator":"AND",
    109. "lenient":false,
    110. "max_expansions":50
    111. }
    112. }
    113. }
    114. ],
    115. "boost":1
    116. }
    117. }
    118. ],
    119. "adjust_pure_negative":true,
    120. "must":[
    121. {
    122. "terms":{
    123. "industryNames":[
    124. "安防",
    125. "办公"
    126. ],
    127. "boost":1
    128. }
    129. }
    130. ],
    131. "boost":1
    132. }
    133. },
    134. "from":0,
    135. "_source":{
    136. "exclude":[
    137. "content"
    138. ]
    139. },
    140. "sort":[
    141. {
    142. "releasedTime":{
    143. "order":"desc"
    144. }
    145. }
    146. ],
    147. "timeout":"20s"
    148. }

    5、Tip

         ES分页搜索,返回条数有限制,最大不能超过1万条,查询总行数会返回正确行数,但超过1万条后返回的数据为空,故,需要在产品设计的时候对前端分页做一下限制,如一页10条数据,最大只展示1000页。

    二、聚合搜索

    1、需求

    • 根据采购单位(orgId)聚合
    • 获取项目数量(projectId去重计数)
    • 金额累计求和(amount求和)
    • 最近一次创建时间 (createTime取max)

    2、DSL查询语句

    1. {
    2. "from":0,
    3. "size":0,
    4. "aggregations":{
    5. "OrgIdGroup":{
    6. "terms":{
    7. "field":"orgId",
    8. "size":10,
    9. "order":[
    10. {
    11. "_count":"desc"
    12. },
    13. {
    14. "_key":"asc"
    15. }
    16. ]
    17. },
    18. "aggregations":{
    19. "projectCount":{
    20. "cardinality":{
    21. "field":"projectId"
    22. }
    23. },
    24. "amountSum":{
    25. "sum":{
    26. "field":"amount"
    27. }
    28. },
    29. "recentCreateTime":{
    30. "max":{
    31. "field":"createTime"
    32. }
    33. }
    34. }
    35. }
    36. }
    37. }

    3、查询结果

    1. {
    2. "_shards": {
    3. "total": 5,
    4. "failed": 0,
    5. "successful": 5,
    6. "skipped": 0
    7. },
    8. "hits": {
    9. "hits": [],
    10. "total": 3,
    11. "max_score": 0
    12. },
    13. "took": 1,
    14. "timed_out": false,
    15. "aggregations": {
    16. "orgIdGroup": {
    17. "doc_count_error_upper_bound": 0,
    18. "sum_other_doc_count": 0,
    19. "buckets": [
    20. {
    21. "doc_count": 2,
    22. "projectCount": {
    23. "value": 1
    24. },
    25. "recentCreateTime": {
    26. "value_as_string": "2023-08-28 02:00:00",
    27. "value": 1693188000000
    28. },
    29. "key": "1000653051",
    30. "amountSum": {
    31. "value": 77700000
    32. }
    33. }
    34. ]
    35. }
    36. }
    37. }

    三、随机排序

    1、需求

       组织机构搜索列表,用户每天登陆系统,看到的组织机构排序顺序是不一样的。(不能排序固定,让一些组织机构总是排序靠前。

    2、DSL查询语句

      在查询语句中加入以下排序内容,random_salt的值可以是md5(当天日期)的结果,用代码获取当天日期md5的值,传入dsl语句中。

      注:代码层增加校验,若用户输入了搜索条件,则dsl语句不需要增加以下排序,否则原本搜索结果是根据匹配度的权重排序的,增加随机排序后会影响查询结果的排序。

    1. {
    2. "_script":{
    3. "script":{
    4. "inline":"(doc['_id'].value + params.random_salt).hashCode()",
    5. "params":{
    6. "random_salt":"这个是动态的"
    7. }
    8. },
    9. "type":"number",
    10. "order":"asc"
    11. }
    12. }
  • 相关阅读:
    分类判别式模型——逻辑斯特回归曲线
    pytorch深度学习实战19
    vuex的使用
    c++设计模式之一创建型模式
    垃圾收集器
    工厂模式 与 抽象工厂模式 的区别
    分布式对象池用哪些组件
    Iview Tree组件点击标题展开
    搞定面试官 - MySQL 中你知道如何计算一个索引的长度嘛?
    java线上CPU、内存打满处理
  • 原文地址:https://blog.csdn.net/zheng911209/article/details/133789057