Query DSL

Elasticsearch以类似于 REST Query DSL 的方式提供了一套完整的java query dsl(Domain Specific Language)。 查询语句构建的factory是 QueryBuilders 。 查询准备就绪之后就可以使用 Search API 了。

要使用 QueryBuilders 只需要在类中引入它们:

import static org.elasticsearch.index.query.QueryBuilders.*;

注意可以使用 QueryBuilder 类中的 toString() 方法方便的打印(调试时)查询语句生成的JSON。

QueryBuilder 可以被用于接受查询语句的任何API中,例如 countsearch

Match All Query

请查看 Match All Query

matchAllQuery();

Full text queries

高级全文检索通常在全文本全字段这样的全文查询时使用,邮件的正文就是这样的例如。 它们了解如何分析所查询的字段,并在查询前将每个字段的 analyzer (或 search_analyzer )应用于查询字符串中。

该组中的查询语句包括:

match query

执行全文检索的标准查询语句,包括模糊匹配、短语匹配和近似匹配。

multi_match query

match query 的多字段版本。

common_terms query

一个更加特殊的查询语句,专门为不常用的词准备。

query_string query

支持Lucene的语法,允许在条件中使用 AND|OR|NOT 和单语多字段查询。 仅供专业用户使用。

simple_query_string

一个 query_string 语法的的更简单且更健壮版本,适合直接开放给用户。

Match Query

查看 Match Query

matchQuery(
        "name", (1)
        "kimchy elasticsearch"); (2)
1 field
2 text

Multi Match Query

multiMatchQuery(
        "kimchy elasticsearch", (1)
        "user", "message"); (2)
1 text
2 fields

Common Terms Query

commonTermsQuery("name", (1)
                 "kimchy"); (2)
1 field
2 value

Query String Query

queryStringQuery("+kimchy -elasticsearch");

Simple Query String Query

simpleQueryStringQuery("+kimchy -elasticsearch");

Term level queries

尽管 full text queries 将在执行之前分析查询语句, 但 term-level queries 会按照存储在反向索引中的确切词进行操作。

这些查询语句通常使用在数字、日期和枚举等结构化数据,而不是全字符串字段。 当然也允许在分析过程之前使用 low-level 查询语句。

这一组中的查询有:

term query

检索指定字段包含指定条件的文档。

terms query

检索指定字段包含指定条件中的任意一个的文档。

range query

检索指定字段包含指定范围内的值(日期、数字或字符串)的文档。

exists query

检索指定字段是否包含非空值的文档。

prefix query

查找指定字段是以指定的条件作为开头的文档。

wildcard query

根据通配符匹配指定字段来检索文档,支持单字符匹配(?)和多字符匹配(*)。

regexp query

根据正则表达式匹配指定字段来检索文档。

fuzzy query

根据模糊相似词检索文档。 模糊度是根据 莱文斯坦距离 1或2来衡量的 。

type query

根据指定类型检索文档。

ids query

根据指定类型和id列表检索文档。

Term Query

查看 Term Query

termQuery(
        "name", (1)
        "kimchy"); (2)
1 field
2 text

Terms Query

查看 Terms Query

termsQuery("tags", (1)
        "blue", "pill"); (2)
1 field
2 values

Range Query

查看 Range Query

rangeQuery("price") (1)
    .from(5) (2)
    .to(10) (3)
    .includeLower(true) (4)
    .includeUpper(false);  (5)
1 字段
2 开始
3 结束
4 是否包含最小值
5 是否包含最大值
// 一种简单的写法是使用 gte(greater than or equal), gt, lt 或 lte(less than or equal)
rangeQuery("age") (1)
    .gte("10") (2)
    .lt("20"); (3)
1 field
2 等价于 from(10)includeLower(true) 两个条件
3 等价于 to(20)includeUpper(false) 两个条件

Exists Query

查看 Exists Query.

existsQuery("name"); (1)
1 field

Prefix Query

查看 Prefix Query

prefixQuery(
        "brand", (1)
        "heine"); (2)
1 field
2 prefix

Wildcard Query

wildcardQuery(
        "user", (1)
        "k?mch*"); (2)
1 字段
2 通配符表达式

Regexp Query

查看 Regexp Query

regexpQuery(
        "name.first", (1)
        "s.*y"); (2)
1 field
2 正则表达式

Fuzzy Query

查看 Fuzzy Query

fuzzyQuery(
        "name", (1)
        "kimchy"); (2)
1 field
2 text

Type Query

查看 Type Query

typeQuery("my_type"); (1)
1 type

Ids Query

查看 Ids Query

idsQuery("my_type", "type2")
        .addIds("1", "4", "100");

idsQuery() (1)
        .addIds("1", "4", "100");
1 type 是可选项

Compound queries

组合查询可以将其它组合查询,以及其它单独的查询语句合并到一起,并将结果和匹配分数组合起来。 它可以改变它们的行为,或是将查询转换为filter context。

这一组中的查询有:

constant_score query

包含其它查询的查询,但却以filter context的形式执行该语句。所有匹配到的文档都会分配相同的 "constant" _score

bool query

使用 must, should, must_not, 或 filter 可以将多个分支或组合查询语句组合到一起。 其中 mustshould 条件的得分会合并到一起,这是大多数时候使用的条件; 而更好的办法是使用 must_notfilter ,这样它们会在 filter context 中执行。

dis_max query

一个接受多个查询语句的查询,匹配到任何查询子句的文档都会返回。 虽然 bool 语句已经将所有匹配结果的得分组合了起来,但 dis_max 的得分却是单条语句匹配的最高得分。

function_score query

使用函数修改主查询返回的分数,以考虑流行性、失效性、距离或使用脚本实现的自定义算法等因素。

boosting query

查询条件将会分为正匹配和负匹配。 positive (正确)匹配到的文档将会加分,negative (负面)匹配得到的文档将会减分。

Constant Score Query

constantScoreQuery(
        termQuery("name","kimchy")) (1)
    .boost(2.0f); (2)
1 your query
2 query score

Bool Query

查看 Bool Query

boolQuery()
        .must(termQuery("content", "test1")) (1)
        .must(termQuery("content", "test4")) (1)
        .mustNot(termQuery("content", "test2")) (2)
        .should(termQuery("content", "test3")) (3)
        .filter(termQuery("content", "test5"));  (4)
1 must query
2 must not query
3 should query
4 绝对匹配,不参与评分。

Dis Max Query

查看 Dis Max Query

disMaxQuery()
        .add(termQuery("name", "kimchy")) (1)
        .add(termQuery("name", "elasticsearch")) (2)
        .boost(1.2f) (3)
        .tieBreaker(0.7f); (4)
1 add your queries
2 add your queries
3 boost factor
4 tie breaker

Function Score Query

想要使用 ScoreFunctionBuilders 只需要在类中引入:

import static org.elasticsearch.index.query.functionscore.ScoreFunctionBuilders.*;
FilterFunctionBuilder[] functions = {
        new FunctionScoreQueryBuilder.FilterFunctionBuilder(
                matchQuery("name", "kimchy"), (1)
                randomFunction()), (2)
        new FunctionScoreQueryBuilder.FilterFunctionBuilder(
                exponentialDecayFunction("age", 0L, 1L)) (3)
};
functionScoreQuery(functions);
1 Add a first function based on a query
2 And randomize the score based on a given seed
3 Add another function based on the age field

Boosting Query

boostingQuery(
            termQuery("name","kimchy"), (1)
            termQuery("name","dadoonet")) (2)
        .negativeBoost(0.2f); (3)
1 query that will promote documents
2 query that will demote documents
3 negative boost

Joining queries

在Elasticsearch这样的分布式系统中使用SQL风格的关联语句对性能的损耗是非常大的。 作为替代,Elasticsearch设计了两种支持水平拓展的关联操作。

nested query

文档可能包含 nested 类型的字段。 这些字段用于索引对象数组,其中每个对象都可以作为独立文档进行查询(使用 nested 查询)。

has_childhas_parent 查询

同一索引之中的文档可以存在父子关系。 has_child 查询会返回子文档匹配的父文档,而 has_parent 查询则会返回父文档匹配的子文档。

Nested Query

查看 Nested Query

nestedQuery(
        "obj1", (1)
        boolQuery() (2)
                .must(matchQuery("obj1.name", "blue"))
                .must(rangeQuery("obj1.count").gt(5)),
        ScoreMode.Avg); (3)
1 嵌套文档的路径
2 查询中使用的所有字段都必须使用完整路径
3 评分模式支持: ScoreMode.Max, ScoreMode.Min, ScoreMode.Total, ScoreMode.AvgScoreMode.None

Has Child Query

使用 has_child 查询的时候有一点很重要的就是使用 PreBuiltTransportClient 而不是普通的client。

Settings settings = Settings.builder().put("cluster.name", "elasticsearch").build();
TransportClient client = new PreBuiltTransportClient(settings);
client.addTransportAddress(new TransportAddress(new InetSocketAddress(InetAddresses.forString("127.0.0.1"), 9300)));

否则父子链接模块将不会被加载,同样的 transport client 中也不能使用 has_child 查询语句。

JoinQueryBuilders.hasChildQuery(
        "blog_tag", (1)
        termQuery("tag","something"), (2)
        ScoreMode.None); (3)
1 child type to query against
2 query
3 评分模式支持: ScoreMode.Avg, ScoreMode.Max, ScoreMode.Min, ScoreMode.NoneScoreMode.Total

Has Parent Query

查看 Has Parent

使用 has_parent 查询的时候有一点很重要的就是使用 PreBuiltTransportClient 而不是普通的client:

Settings settings = Settings.builder().put("cluster.name", "elasticsearch").build();
TransportClient client = new PreBuiltTransportClient(settings);
client.addTransportAddress(new TransportAddress(new InetSocketAddress(InetAddresses.forString("127.0.0.1"), 9300)));

否则父子链接模块将不会被加载,同样的 transport client 中也不能使用 has_child 查询语句。

JoinQueryBuilders.hasParentQuery(
    "blog", (1)
    termQuery("tag","something"), (2)
    false); (3)
1 parent type to query against
2 query
3 是否将父文档匹配分数传递给子文档

Geo queries

Elasticsearch支持两种类型的地理位置数据:支持经纬度的 geo_point ,以及支持点、线、圆、多边形等的 geo_shape

该组中的查询语句包括:

geo_shape 查询

可以匹配坐标与指定区域相交、不相交或包含的地理位置。

geo_bounding_box 查询

可以匹配坐标在矩形区域的地理位置。

geo_distance 查询

可以查询指定坐标为中心点指定距离内的地理位置。

geo_polygon 查询

可以查询坐标在多边形范围内的地理位置。

GeoShape Query

Note: geo_shape 类型使用 Spatial4JJTS 两种依赖。 因此,必须将 Spatial4JJTS 添加到 classpath中才能使用这种类型:

<dependency>
    <groupId>org.locationtech.spatial4j</groupId>
    <artifactId>spatial4j</artifactId>
    <version>0.7</version>  (1)
</dependency>

<dependency>
    <groupId>org.locationtech.jts</groupId>
    <artifactId>jts-core</artifactId>
    <version>1.15.0</version> (2)
    <exclusions>
        <exclusion>
            <groupId>xerces</groupId>
            <artifactId>xercesImpl</artifactId>
        </exclusion>
    </exclusions>
</dependency>
1 Maven Central 中查看更新
2 Maven Central 中查看更新
// Import ShapeRelation and ShapeBuilder
import org.elasticsearch.common.geo.ShapeRelation;
import org.elasticsearch.common.geo.builders.ShapeBuilder;
GeoShapeQueryBuilder qb = geoShapeQuery(
        "pin.location", (1)
        new MultiPointBuilder( (2)
                new CoordinatesBuilder()
            .coordinate(0, 0)
            .coordinate(0, 10)
            .coordinate(10, 10)
            .coordinate(10, 0)
            .coordinate(0, 0)
            .build()));
qb.relation(ShapeRelation.WITHIN); (3)
1 field
2 shape
3 关系可以是 ShapeRelation.CONTAINS, ShapeRelation.WITHIN, ShapeRelation.INTERSECTSShapeRelation.DISJOINT
// Using pre-indexed shapes
GeoShapeQueryBuilder qb = geoShapeQuery(
            "pin.location", (1)
            "DEU", (2)
            "countries"); (3)
qb.relation(ShapeRelation.WITHIN) (4)
    .indexedShapeIndex("shapes") (5)
    .indexedShapePath("location");  (6)
1 field
2 包含pre-indexed形状的文档ID
3 包含pre-indexed形状的index type
4 relation
5 包含pre-indexed形状的index名,默认是shapes
6 包含pre-indexed形状的字段名,默认是’shape'

Geo Bounding Box Query

geoBoundingBoxQuery("pin.location") (1)
    .setCorners(40.73, -74.1, (2)
                40.717, -73.99); (3)
1 field
2 矩形左上角的坐标点
3 矩形右上角的坐标点

Geo Distance Query

geoDistanceQuery("pin.location") (1)
    .point(40, -70) (2)
    .distance(200, DistanceUnit.KILOMETERS); (3)
1 field
2 中心点坐标
3 和中心点的距离

Geo Polygon Query

List<GeoPoint> points = new ArrayList<GeoPoint>(); (1)
points.add(new GeoPoint(40, -70));
points.add(new GeoPoint(30, -80));
points.add(new GeoPoint(20, -90));
geoPolygonQuery("pin.location", points); (2)
1 添加落在多边形上的点的坐标
2 通过字段和点初始化查询语句

Specialized queries

该组查询中包含以下这些不适用于其它查询的语句:

more_like_this query

这个查询语句可以检索出和指定的文本、文档或文档集合相似的文档。

script query

这个查询语句可以将脚本作为过滤器来适用。请查看 function_score query

percolate query

This query finds percolator queries based on documents.

wrapper query

可以接受Json和Yaml类型语句的查询。

More Like This Query

String[] fields = {"name.first", "name.last"}; (1)
String[] texts = {"text like this one"}; (2)

moreLikeThisQuery(fields, texts, null)
    .minTermFreq(1) (3)
    .maxQueryTerms(12); (4)
1 fields
2 text
3 忽略阈值
4 生成语句条件的最大字数

Script Query

查看 Script Query

scriptQuery(
        new Script("doc['num1'].value > 1") (1)
    );
1 定义脚本

如果数据节点上已经存储了脚本,例如叫 myscript.painless :

doc['num1'].value > params.param1

你就可以这样使用它:

Map<String, Object> parameters = new HashMap<>();
parameters.put("param1", 5);
scriptQuery(new Script(
        ScriptType.STORED, (1)
        null, (2)
        "myscript", (3)
        singletonMap("param1", 5))); (4)
1 Script type: either ScriptType.FILE, ScriptType.INLINE or ScriptType.INDEXED
2 Scripting engine
3 Script name
4 Parameters as a Map<String, Object>

Percolate Query

查看: * Percolate Query

Settings settings = Settings.builder().put("cluster.name", "elasticsearch").build();
TransportClient client = new PreBuiltTransportClient(settings);
client.addTransportAddress(new TransportAddress(new InetSocketAddress(InetAddresses.forString("127.0.0.1"), 9300)));

在使用 percolate 查询之前,应该添加 percolate 的映射,并且应该对包含 percolate 查询的文档建立索引:

// create an index with a percolator field with the name 'query':
client.admin().indices().prepareCreate("myIndexName")
                        .addMapping("_doc", "query", "type=percolator", "content", "type=text")
                        .get();

//This is the query we're registering in the percolator
QueryBuilder qb = termQuery("content", "amazing");

//Index the query = register it in the percolator
client.prepareIndex("myIndexName", "_doc", "myDesignatedQueryName")
    .setSource(jsonBuilder()
        .startObject()
            .field("query", qb) // Register the query
        .endObject())
    .setRefreshPolicy(RefreshPolicy.IMMEDIATE) // Needed when the query shall be available immediately
    .get();

查询语句会在 myDesignatedQueryName 的下面建立索引。

为了对照已注册的查询语句检查文档,可以使用如下代码:

//Build a document to check against the percolator
XContentBuilder docBuilder = XContentFactory.jsonBuilder().startObject();
docBuilder.field("content", "This is amazing!");
docBuilder.endObject(); //End of the JSON root object

PercolateQueryBuilder percolateQuery = new PercolateQueryBuilder("query", "_doc", BytesReference.bytes(docBuilder));

// Percolate, by executing the percolator query in the query dsl:
SearchResponse response = client().prepareSearch("myIndexName")
        .setQuery(percolateQuery))
        .get();
//Iterate over the results
for(SearchHit hit : response.getHits()) {
    // Percolator queries as hit
}

Wrapper Query

查看 Wrapper Query

String query = "{\"term\": {\"user\": \"kimchy\"}}"; (1)
wrapperQuery(query);
1 query defined as query builder

Span queries

Span queries 是一种低级别的位置查询语句,它提供对排序和相似度更专业的控制。 通常用在法律文件或专利这样非常具体的查询。

Span queries不能和non-span queries(span_multi query 是个例外)混合使用。

该组中包括以下查询:

span_term query

等同于 term query ,但用于其它跨度查询。

span_multi query

包括 term, range, prefix, wildcard, regexp, 或 fuzzy 这些查询语句。

span_first query

接收另一个 span query,它的匹配项必须出现在该字段的前 N 个位置。

span_near query

接受在指定距离内其它的span queries,并且可以是以相同的顺序。

span_or query

将多个span queries组合起来,并返回任何匹配的文档。

span_not query

包含其它span query,并排除匹配的文档。

span_containing query

接受一个span queries列表,但只返回两个条件都匹配的文档。

span_within query

只要span query落在由其它span queries中,就会返回span query的结果。

Span Term Query

spanTermQuery(
        "user",  (1)
        "kimchy");  (2)
1 field
2 value

Span Multi Term Query

spanMultiTermQueryBuilder(
        prefixQuery("user", "ki")); (1)
1 支持任何继承 MultiTermQueryBuilder 的类,比如 FuzzyQueryBuilder , PrefixQueryBuilder, RangeQueryBuilder, RegexpQueryBuilderWildcardQueryBuilder.

Span First Query

spanFirstQuery(
        spanTermQuery("user", "kimchy"), (1)
        3 (2)
    );
1 query
2 最大结束点位置

Span Near Query

spanNearQuery(
        spanTermQuery("field","value1"), (1)
        12) (2)
            .addClause(spanTermQuery("field","value2")) (3)
            .addClause(spanTermQuery("field","value3")) (4)
            .inOrder(false); (5)
1 span queries 条件
2 不匹配的最大数量
3 span queries 条件
4 span queries 条件
5 匹配之后是否需要排序

Span Or Query

查看 Span Or Query

spanOrQuery(spanTermQuery("field","value1")) (1)
    .addClause(spanTermQuery("field","value2")) (2)
    .addClause(spanTermQuery("field","value3")); (3)
1 span queries 条件

Span Not Query

spanNotQuery(
        spanTermQuery("field","value1"), (1)
        spanTermQuery("field","value2")); (2)
1 需要进行过滤的 span query
2 需要排除的 span query

Span Containing Query

spanContainingQuery(
        spanNearQuery(spanTermQuery("field1","bar"), 5) (1)
            .addClause(spanTermQuery("field1","baz"))
            .inOrder(true),
        spanTermQuery("field1","foo")); (2)
1 的部分
2 的部分

Span Within Query

spanWithinQuery(
        spanNearQuery(spanTermQuery("field1", "bar"), 5) (1)
            .addClause(spanTermQuery("field1", "baz"))
            .inOrder(true),
        spanTermQuery("field1", "foo")); (2)
1 的部分
2 的部分