ES6.6.2 使用小结 - 封装ES常用的查询方法

梦里梦外; 2022-02-27 03:44 687阅读 0赞

1.首先,接下来的查询demo里面包含了10常用的方法:term查询、terms查询、range查询、exists查询、prefix查询、wildcard查询、regexp查询、fuzzy查询、type查询、ids查询。

2.以下是封装了10个常用方法的QueryUtil:

  1. package com.bas.util;
  2. import org.elasticsearch.action.search.SearchResponse;
  3. import org.elasticsearch.client.transport.TransportClient;
  4. import org.elasticsearch.index.query.QueryBuilders;
  5. import org.elasticsearch.search.SearchHit;
  6. import org.elasticsearch.search.SearchHits;
  7. import org.elasticsearch.index.query.QueryBuilder;
  8. import java.util.ArrayList;
  9. import java.util.List;
  10. import java.util.Map;
  11. public class QueryUtil {
  12. private static SearchHits hits;
  13. private static TransportClient client = ESUtil.getClient();
  14. /**
  15. * 打印常见信息
  16. */
  17. public static void print() {
  18. if (hits == null) {
  19. return;
  20. }
  21. System.out.println("-> totalHits: "+hits.totalHits);
  22. for (SearchHit hit : hits) {
  23. System.out.println("-----------");
  24. System.out.println("source:" + hit.getSourceAsString());
  25. System.out.println("index:" + hit.getIndex());
  26. System.out.println("type:" + hit.getType());
  27. System.out.println("id:" + hit.getId());
  28. //遍历文档的每个字段
  29. Map<String, Object> map = hit.getSourceAsMap();
  30. for (String key : map.keySet()) {
  31. System.out.println(key + "=" + map.get(key));
  32. }
  33. System.out.println("HighlightFields:" + hit.getHighlightFields());
  34. System.out.println("Fields:" + hit.getFields());
  35. System.out.println("MatchedQueries:" + hit.getMatchedQueries());
  36. System.out.println("InnerHits:" + hit.getInnerHits());
  37. System.out.println("-----------");
  38. }
  39. }
  40. /**
  41. * 执行查询
  42. *
  43. * @param query 查询器
  44. * @return 当前查询对象
  45. */
  46. private static List<Map<String, Object>> executeQuery(QueryBuilder query, String indexName, int size) {
  47. //搜索结果存入SearchResponse
  48. SearchResponse response = client.prepareSearch(indexName)
  49. .setQuery(query) //设置查询器
  50. .setSize(size) //一次查询文档数
  51. .get();
  52. hits = response.getHits();
  53. if (hits == null) {
  54. return null;
  55. }
  56. List<Map<String, Object>> resultList = new ArrayList<>();
  57. for (SearchHit hit : hits) {
  58. resultList.add(hit.getSourceAsMap());
  59. }
  60. print();
  61. return resultList;
  62. }
  63. /**
  64. * Find documents which contain the exact term specified in the field specified.
  65. * 单个精确词项查询,内容有中文不能匹配
  66. * @param indexName 索引名
  67. * @param size 数据量
  68. * @param field 查询字段
  69. * @param termValue 单个词项内容
  70. * @return 结果集
  71. */
  72. public synchronized static List<Map<String, Object>> termQuery(String indexName, int size, String field, String termValue) {
  73. QueryBuilder qb = QueryBuilders.termQuery(field, termValue);
  74. return executeQuery(qb, indexName, size);
  75. }
  76. /**
  77. * Find documents which contain any of the exact terms specified in the field specified.
  78. * 多个精确词项查询,内容有中文不能匹配
  79. * @param indexName 索引名
  80. * @param size 数据量
  81. * @param field 查询字段
  82. * @param termValue 单个词项内容
  83. * @return 结果集
  84. */
  85. public synchronized static List<Map<String, Object>> termsQuery(String indexName, int size, String field, String ...termValue) {
  86. QueryBuilder qb = QueryBuilders.termsQuery(field, termValue);
  87. return executeQuery(qb, indexName, size);
  88. }
  89. /**
  90. * Find documents where the field specified
  91. * contains values (dates, numbers, or strings) in the range specified.
  92. * @param indexName 索引名
  93. * @param size 数据量
  94. * @param field 查询字段
  95. * @param from 起始时间
  96. * @param to 截止时间
  97. * @return 结果集
  98. */
  99. public synchronized static List<Map<String, Object>> rangeQuery(String indexName, int size, String field, String from, String to) {
  100. QueryBuilder qb = QueryBuilders.rangeQuery(field).from(from).to(to);
  101. return executeQuery(qb, indexName, size);
  102. }
  103. /**
  104. * Find documents where the field specified contains any non-null value.
  105. * 查找包含任何非空值的文档的指定字段
  106. * @param indexName 索引名
  107. * @param size 数据量
  108. * @param field 查询字段
  109. * @return 结果集
  110. */
  111. public synchronized static List<Map<String, Object>> existsQuery(String indexName, int size, String field) {
  112. QueryBuilder qb = QueryBuilders.existsQuery(field);
  113. return executeQuery(qb, indexName, size);
  114. }
  115. /**
  116. * Find documents where the field specified contains terms
  117. * which being with the exact prefix specified.
  118. * 匹配包含xx前缀的文档,内容有中文不能匹配
  119. * @param indexName 索引名
  120. * @param size 数据量
  121. * @param field 查询字段
  122. * @param prefixValue 前缀内容
  123. * @return 结果集
  124. */
  125. public synchronized static List<Map<String, Object>> prefixQuery(String indexName, int size, String field, String prefixValue) {
  126. QueryBuilder qb = QueryBuilders.prefixQuery(field, prefixValue);
  127. return executeQuery(qb, indexName, size);
  128. }
  129. /**
  130. * Find documents where the field specified contains terms
  131. * which match the pattern specified,
  132. * where the pattern supports single character wildcards (?)
  133. * and multi-character wildcards (*)
  134. * 通配符匹配查询,内容有中文不能匹配
  135. * @param indexName 索引名
  136. * @param size 数据量
  137. * @param field 查询字段
  138. * @param wildcardValue 包含通配符的内容
  139. * @return 结果集
  140. */
  141. public synchronized static List<Map<String, Object>> wildcardQuery(String indexName, int size, String field, String wildcardValue) {
  142. QueryBuilder qb = QueryBuilders.wildcardQuery(field, wildcardValue);
  143. return executeQuery(qb, indexName, size);
  144. }
  145. /**
  146. * Find documents where the field specified contains terms
  147. * which match the regular expression specified.
  148. * 正则匹配查询,内容有中文不能匹配
  149. * @param indexName 索引名
  150. * @param size 数据量
  151. * @param field 查询字段
  152. * @param regexpValue 包含正则的内容
  153. * @return 结果集
  154. */
  155. public synchronized static List<Map<String, Object>> regexpQuery(String indexName, int size, String field, String regexpValue) {
  156. QueryBuilder qb = QueryBuilders.regexpQuery(field, regexpValue);
  157. return executeQuery(qb, indexName, size);
  158. }
  159. /**
  160. * Find documents where the field specified contains terms
  161. * which are fuzzily similar to the specified term.
  162. * Fuzziness is measured as a Levenshtein edit distance of 1 or 2.
  163. * 模糊查询,内容有中文不能匹配
  164. * @param indexName 索引名
  165. * @param size 数据量
  166. * @param field 查询字段
  167. * @param fuzzyValue 模糊值
  168. * @return 结果集
  169. */
  170. public synchronized static List<Map<String, Object>> fuzzyQuery(String indexName, int size, String field, String fuzzyValue) {
  171. QueryBuilder qb = QueryBuilders.fuzzyQuery(field, fuzzyValue);
  172. return executeQuery(qb, indexName, size);
  173. }
  174. /**
  175. * Find documents of the specified type.
  176. * 查询指定type名的文档
  177. * @param indexName 索引名
  178. * @param size 数据量
  179. * @param type type名
  180. * @return 结果集
  181. */
  182. public synchronized static List<Map<String, Object>> typeQuery(String indexName, int size, String type) {
  183. QueryBuilder qb = QueryBuilders.typeQuery(type);
  184. return executeQuery(qb, indexName, size);
  185. }
  186. /**
  187. * Find documents with the specified type and IDs.
  188. * 根据指定的type和文档id查询
  189. * @param indexName 索引名
  190. * @param size 数据量
  191. * @param ids 文档的_id
  192. * @return 结果集
  193. */
  194. public synchronized static List<Map<String, Object>> idsQuery(String indexName, int size, String ...ids) {
  195. QueryBuilder qb = QueryBuilders.idsQuery(ids);
  196. return executeQuery(qb, indexName, size);
  197. }
  198. }

其中,ES工具类位于:ES6.6.2 使用小结 - ES工具类使用

  1. 测试每个方法的测试类MatchQueryDemo如下:

    package com.bas.demo;

    import com.bas.util.ESUtil;
    import com.bas.util.QueryUtil;
    import org.elasticsearch.action.search.SearchResponse;
    import org.elasticsearch.client.transport.TransportClient;
    import org.elasticsearch.index.query.Operator;
    import org.elasticsearch.index.query.QueryBuilder;
    import org.elasticsearch.index.query.QueryBuilders;
    import org.elasticsearch.search.SearchHit;
    import org.elasticsearch.search.SearchHits;
    import org.junit.jupiter.api.Test;

    import java.util.Map;

    public class MatchQueryDemo {

    1. /**
    2. * 全量查询
    3. *
    4. * @param args
    5. */
    6. public static void main(String[] args) {
    7. TransportClient client = ESUtil.getClient();
    8. //构造查询对象
    9. QueryBuilder query = QueryBuilders.matchAllQuery();
    10. //搜索结果存入SearchResponse
    11. SearchResponse response = client.prepareSearch("app_account")
    12. .setQuery(query) //设置查询器
    13. .setSize(3) //一次查询文档数
    14. .get();
    15. SearchHits hits = response.getHits();
    16. int count = 1;
    17. for (SearchHit hit : hits) {
    18. System.out.println("--------------------" + count++);
    19. System.out.println("source:" + hit.getSourceAsString());
    20. System.out.println("index:" + hit.getIndex());
    21. System.out.println("type:" + hit.getType());
    22. System.out.println("id:" + hit.getId());
    23. //遍历文档的每个字段
    24. Map<String, Object> map = hit.getSourceAsMap();
    25. for (String key : map.keySet()) {
    26. System.out.println(key + "=" + map.get(key));
    27. }
    28. System.out.println("--------------------\n");
    29. }
    30. }
    31. /**
    32. * 单个字段匹配查询
    33. */
    34. @Test
    35. public void matchQuery() {
    36. SearchHits hits;
    37. //构造查询对象
    38. QueryBuilder query = QueryBuilders.matchQuery(
    39. "title",
    40. "标题");
    41. SearchResponse response = ESUtil.getClient().prepareSearch("app_account")
    42. .setQuery(query) //设置查询器
    43. .setSize(5) //一次查询文档数
    44. .get();
    45. hits = response.getHits();
    46. for (SearchHit hit : hits) {
    47. System.out.println("source:" + hit.getSourceAsString());
    48. System.out.println("index:" + hit.getIndex());
    49. System.out.println("type:" + hit.getType());
    50. System.out.println("id:" + hit.getId());
    51. //遍历文档的每个字段
    52. Map<String, Object> map = hit.getSourceAsMap();
    53. for (String key : map.keySet()) {
    54. System.out.println(key + "=" + map.get(key));
    55. }
    56. System.out.println("HighlightFields:" + hit.getHighlightFields());
    57. System.out.println("Fields:" + hit.getFields());
    58. System.out.println("MatchedQueries:" + hit.getMatchedQueries().length);
    59. System.out.println("InnerHits:" + hit.getInnerHits());
    60. }
    61. }
    62. /**
    63. * 操作符查询
    64. */
    65. @Test
    66. public void operatorQuery() {
    67. SearchHits hits;
    68. //构造查询对象
    69. QueryBuilder query = QueryBuilders.matchQuery(
    70. "title",
    71. "标题").operator(Operator.AND);
    72. SearchResponse response = ESUtil.getClient().prepareSearch("app_account")
    73. .setQuery(query) //设置查询器
    74. .setSize(5) //一次查询文档数
    75. .get();
    76. hits = response.getHits();
    77. for (SearchHit hit : hits) {
    78. System.out.println("--------");
    79. System.out.println("source:" + hit.getSourceAsString());
    80. System.out.println("index:" + hit.getIndex());
    81. System.out.println("type:" + hit.getType());
    82. System.out.println("id:" + hit.getId());
    83. //遍历文档的每个字段
    84. Map<String, Object> map = hit.getSourceAsMap();
    85. for (String key : map.keySet()) {
    86. System.out.println(key + "=" + map.get(key));
    87. }
    88. System.out.println("HighlightFields:" + hit.getHighlightFields());
    89. System.out.println("Fields:" + hit.getFields());
    90. System.out.println("--------");
    91. }
    92. }
    93. /**
    94. * 多字段同时匹配查询
    95. * 内容有中文不能匹配
    96. */
    97. @Test
    98. public void multiMatchQuery() {
    99. SearchHits hits;
    100. //构造查询对象
    101. QueryBuilder query = QueryBuilders.multiMatchQuery(
    102. "bas",
    103. "title", "url");
    104. SearchResponse response = ESUtil.getClient().prepareSearch("app_account")
    105. .setQuery(query) //设置查询器
    106. .setSize(5) //一次查询文档数
    107. .get();
    108. hits = response.getHits();
    109. for (SearchHit hit : hits) {
    110. System.out.println("source:" + hit.getSourceAsString());
    111. System.out.println("index:" + hit.getIndex());
    112. System.out.println("type:" + hit.getType());
    113. System.out.println("id:" + hit.getId());
    114. //遍历文档的每个字段
    115. Map<String, Object> map = hit.getSourceAsMap();
    116. for (String key : map.keySet()) {
    117. System.out.println(key + "=" + map.get(key));
    118. }
    119. System.out.println("HighlightFields:" + hit.getHighlightFields());
    120. System.out.println("Fields:" + hit.getFields());
    121. }
    122. }
    123. /**
    124. * 单个词项精确查询,内容有中文不能匹配
    125. */
    126. @Test
    127. public void termQuery() {
    128. QueryUtil.termQuery("app_account", 5, "url", "bas");
    129. }
    130. /**
    131. * 多个词项精确查询,内容有中文不能匹配
    132. */
    133. @Test
    134. public void termsQuery() {

    // QueryUtil.termsQuery(“app_account”, 5, “title.keyword”, “更新title”, “标题”); // 这样就可以匹配中文了,或者修改mapping的字段属性为不分词

    1. QueryUtil.termsQuery("app_account", 5, "title", "更新title", "标题");
    2. }
    3. @Test
    4. public void rangeQuery() {
    5. QueryUtil.rangeQuery("app_account", 100, "postdate", "2017-03-24", "2019-03-24");
    6. }
    7. @Test
    8. public void existsQuery() {
    9. QueryUtil.existsQuery("app_account", 100, "postdate");
    10. }
    11. /**
    12. * 匹配包含xx前缀的文档,内容有中文不能匹配
    13. */
    14. @Test
    15. public void prefixQuery() {

    // QueryUtil.prefixQuery(“app_account”, 100, “title.keyword”,”标题”); // 这样就可以匹配中文了

    1. QueryUtil.prefixQuery("app_account", 100, "title.keyword", "标题");
    2. }
    3. /**
    4. * 通配符匹配查询,内容有中文不能匹配
    5. */
    6. @Test
    7. public void wildcardQuery() {

    // QueryUtil.wildcardQuery(“app_account”, 100, “title.keyword”, “标题*”);

    1. QueryUtil.wildcardQuery("app_account", 100, "title", "标题*");
    2. }
    3. /**
    4. * 正则匹配查询,内容有中文不能匹配
    5. */
    6. @Test
    7. public void regexpQuery() {

    // QueryUtil.regexpQuery(“app_account”, 100, “title.keyword”, “标题.*”);

    1. QueryUtil.regexpQuery("app_account", 100, "title", "标题.*");
    2. }
    3. /**
    4. * 模糊查询,内容有中文不能匹配
    5. * 字段名加上.keyword也不能匹配中文
    6. */
    7. @Test
    8. public void fuzzyQuery() {

    // QueryUtil.fuzzyQuery(“app_account”, 100, “title.keyword”, “标题”);

    1. QueryUtil.fuzzyQuery("app_account", 100, "title", "asd");
    2. }
    3. @Test
    4. public void typeQuery() {
    5. QueryUtil.typeQuery("app_account", 5, "blog");
    6. }
    7. @Test
    8. public void idsQuery() {
    9. QueryUtil.idsQuery("app_account", 5, "asdasdcVcCKaQfGQ3", "52AbtWkBqLTNcYM2gf0z", "62AltWkBqLTNcYM27f2h");
    10. }

    }

1.应该会有不少人会发现,ES的查询器的有些方法可能会不能匹配中文,正如测试类的注释说的,在查询字段后加上:.keyword,如图:

20190326182255843.png

2.如果不想每次增加.keyword来匹配中文内容,建立mapping 的时候可以设置”index”: “not_analyzed”,这样也可以实现。

附(两篇和ES常用方法的文章)

1.https://www.cnblogs.com/fclbky/p/7124469.html

2.https://www.jianshu.com/p/14ac79f93a38

发表评论

表情:
评论列表 (有 0 条评论,687人围观)

还没有评论,来说两句吧...

相关阅读