Query DSL

Elasticsearch provides a full Query DSL (Domain Specific Language) based on JSON to define queries. Think of the Query DSL as an AST (Abstract Syntax Tree) of queries, consisting of two types of clauses:
Leaf query clauses
Leaf query clauses look for a particular value in a particular field, such as the match, term or range queries. These queries can be used by themselves.
Compound query clauses
Compound query clauses wrap other leaf or compound queries and are used to combine multiple queries in a logical fashion (such as the bool or dis_max query), or to alter their behaviour (such as the constant_score query).
Query clauses behave differently depending on whether they are used in query context or filter context.

查询构造

Ref: https://blog.csdn.net/weixin_39913422/article/details/111218265

等值查询

  1. BoolQueryBuilder queryBuilder = QueryBuilders.boolQuery()
  2. .must(QueryBuilders.termQuery("name", "小李"));

相当于:

  1. {
  2. "query": {
  3. "bool": {
  4. "adjust_pure_negative": true,
  5. "must": [
  6. {
  7. "term": {
  8. "name": {
  9. "boost": 1,
  10. "value": "小李"
  11. }
  12. }
  13. }
  14. ],
  15. "boost": 1
  16. }
  17. }
  18. }

范围查询

  1. BoolQueryBuilder queryBuilder = QueryBuilders.rangeQuery("age").gte(18).lte(50);

相当于:

  1. {
  2. "query": {
  3. "range": {
  4. "age": {
  5. "include_lower": true,
  6. "include_upper": true,
  7. "from": 18,
  8. "boost": 1,
  9. "to": 50
  10. }
  11. }
  12. }
  13. }

模糊查询

  1. BoolQueryBuilder queryBuilder = QueryBuilders.boolQuery()
  2. .must(QueryBuilders.wildcardQuery("name", "*小李*"));

相当于:

  1. {
  2. "query": {
  3. "bool": {
  4. "adjust_pure_negative": true,
  5. "must": [
  6. {
  7. "wildcard": {
  8. "name": {
  9. "boost": 1,
  10. "wildcard": "*小李*"
  11. }
  12. }
  13. }
  14. ],
  15. "boost": 1
  16. }
  17. }
  18. }

多条件查询

  1. BoolQueryBuilder queryBuilder = QueryBuilders.boolQuery()
  2. .must(QueryBuilders.termQuery("name", "小李"))
  3. .must(QueryBuilders.rangeQuery("age").gte(10).lte(50));

查询姓名为:小李,并且年龄在10-50之间的文档,等同于以下命令:

  1. {
  2. "query": {
  3. "bool": {
  4. "adjust_pure_negative": true,
  5. "must": [
  6. {
  7. "term": {
  8. "name": {
  9. "boost": 1.0,
  10. "value": "小李"
  11. }
  12. }
  13. },
  14. {
  15. "range": {
  16. "age": {
  17. "include_lower": true,
  18. "include_upper": true,
  19. "from": 10,
  20. "boost": 1.0,
  21. "to": 50
  22. }
  23. }
  24. }
  25. ],
  26. "boost": 1.0
  27. }
  28. }
  29. }

集合查询

  1. List < String > list = Arrays.asList("北京", "上海", "杭州");
  2. BoolQueryBuilder queryBuilder = QueryBuilders.boolQuery()
  3. .must(QueryBuilders.termQuery("name", "李明"))
  4. .must(QueryBuilders.termsQuery("address", list))
  5. .must(QueryBuilders.rangeQuery("age").gte(10).lte(50));

查询地址在北京、上海、杭州,并且年龄在10至50,名字叫做李明的文档,等同于以下命令:

  1. {
  2. "query": {
  3. "bool": {
  4. "adjust_pure_negative": true,
  5. "must": [
  6. {
  7. "term": {
  8. "name": {
  9. "boost": 1.0,
  10. "value": "李明"
  11. }
  12. }
  13. },
  14. {
  15. "terms": {
  16. "address": [
  17. "北京",
  18. "上海",
  19. "杭州"
  20. ],
  21. "boost": 1.0
  22. }
  23. },
  24. {
  25. "range": {
  26. "age": {
  27. "include_lower": true,
  28. "include_upper": true,
  29. "from": 10,
  30. "boost": 1.0,
  31. "to": 50
  32. }
  33. }
  34. }
  35. ],
  36. "boost": 1.0
  37. }
  38. }
  39. }

使用 should 查询

  1. BoolQueryBuilder queryBuilder = QueryBuilders.boolQuery()
  2. .should(QueryBuilders.wildcardQuery("name", "*小李*"))
  3. .should(QueryBuilders.termQuery("address", "北京"));

查询姓名包含小李或者是地址是北京的记录,should 相当于 or,命令如下:

  1. {
  2. "query":
  3. {
  4. "bool":
  5. {
  6. "adjust_pure_negative": true,
  7. "should": [
  8. {
  9. "wildcard":
  10. {
  11. "name":
  12. {
  13. "boost": 1.0,
  14. "wildcard": "*小李*"
  15. }
  16. }
  17. },
  18. {
  19. "term":
  20. {
  21. "address":
  22. {
  23. "boost": 1.0,
  24. "value": "北京"
  25. }
  26. }
  27. }],
  28. "boost": 1.0
  29. }
  30. }
  31. }

should 和 must 组合查询

  1. BoolQueryBuilder queryBuilder = QueryBuilders.boolQuery()
  2. .must(QueryBuilders.termQuery("sex", "男"))
  3. .should(QueryBuilders.wildcardQuery("name", "*小李*"))
  4. .should(QueryBuilders.termQuery("address", "北京"))
  5. .minimumShouldMatch(1);

查询性别为男,姓名包含小李或地址为北京的记录,minimumShouldMatch(1) 表示最少要匹配到一个 should 条件。相当于以下命令:

  1. {
  2. "query":
  3. {
  4. "bool":
  5. {
  6. "adjust_pure_negative": true,
  7. "should": [
  8. {
  9. "wildcard":
  10. {
  11. "name":
  12. {
  13. "boost": 1.0,
  14. "wildcard": "*小李*"
  15. }
  16. }
  17. },
  18. {
  19. "term":
  20. {
  21. "address":
  22. {
  23. "boost": 1.0,
  24. "value": "北京"
  25. }
  26. }
  27. }],
  28. "minimum_should_match": "1",
  29. "must": [
  30. {
  31. "term":
  32. {
  33. "sex":
  34. {
  35. "boost": 1.0,
  36. "value": "男"
  37. }
  38. }
  39. }],
  40. "boost": 1.0
  41. }
  42. }
  43. }
  44. {
  45. "query":
  46. {
  47. "bool":
  48. {
  49. "adjust_pure_negative": true,
  50. "should": [
  51. {
  52. "wildcard":
  53. {
  54. "name":
  55. {
  56. "boost": 1.0,
  57. "wildcard": "*小李*"
  58. }
  59. }
  60. },
  61. {
  62. "term":
  63. {
  64. "address":
  65. {
  66. "boost": 1.0,
  67. "value": "北京"
  68. }
  69. }
  70. }],
  71. "minimum_should_match": "1",
  72. "must": [
  73. {
  74. "term":
  75. {
  76. "sex":
  77. {
  78. "boost": 1.0,
  79. "value": "男"
  80. }
  81. }
  82. }],
  83. "boost": 1.0
  84. }
  85. }
  86. }

有值查询

  1. BoolQueryBuilder queryBuilder = QueryBuilders.boolQuery()
  2. .must(QueryBuilders.existsQuery("name"))
  3. .mustNot(QueryBuilders.existsQuery("tag"));

查询 name 有值,tag 不存在值的文档,命令如下:

  1. {
  2. "query":
  3. {
  4. "bool":
  5. {
  6. "adjust_pure_negative": true,
  7. "must_not": [
  8. {
  9. "exists":
  10. {
  11. "field": "tag",
  12. "boost": 1.0
  13. }
  14. }],
  15. "must": [
  16. {
  17. "exists":
  18. {
  19. "field": "name",
  20. "boost": 1.0
  21. }
  22. }],
  23. "boost": 1.0
  24. }
  25. }
  26. }

分页查询

  1. SearchResponse response = this.transportClient.prepareSearch(index)
  2. .setTypes(type)
  3. .setQuery(queryBuilder)
  4. .setFrom(offset)
  5. .setSize(rows)
  6. .setExplain(false)
  7. .execute().actionGet();

普通分页查询数据,相当于以下命令:

{
    "from": 0,
    "size": 10,
    "query":
    {
        "bool":
        {
            "adjust_pure_negative": true,
            "must": [
            {
                "term":
                {
                    "name":
                    {
                        "boost": 1.0,
                        "value": "小李"
                    }
                }
            }],
            "boost": 1.0
        }
    }
}

基于 scrollId 查询的API如下:

SearchResponse scrollResp = null;
String scrollId = ContextParameterHolder.get("scrollId");
if(scrollId != null)
{
    scrollResp = getTransportClient().prepareSearchScroll(scrollId).setScroll(new TimeValue(60000)).execute().actionGet();
}
else
{
    log.info("基于scroll的分页查询,scrollId为空");
    scrollResp = this.prepareSearch()
        .setSearchType(SearchType.QUERY_AND_FETCH)
        .setScroll(new TimeValue(60000))
        .setQuery(queryBuilder)
        .setSize(page.getPageSize()).execute().actionGet();
    ContextParameterHolder.set("scrollId", scrollResp.getScrollId());
}