orderBy -> 排序
orderBy
子句翻译为 ElasticSearch 排序。
firstRows/maxRows -> from/size
firstRows
和 maxRows
分别翻译为 ElasticSearch from 和 size。
select/fetch -> fields/include
ORM 查询的 select
和 fetch
子句翻译为 ElasticSearch fields 和 _source include。背景知识阅读请参阅 搜索时管理 elasticsearch 字段。
如果获取是 *
“获取路径的所有属性”或路径是 OneToMany 或 ManyToMany,Ebean 将获取() 子句翻译为 _source include。
预期将有一些我们想要优化的特定查询(以支持自动完成 UI 等),对于这些查询,我们可以存储我们想要获取的字段(以便 ElasticSearch 不需要从 _source 中读取它们),然后使用字段来专门只获取那些字段。预期的用例是支持“客户名称”或“产品名称”等的自动完成,我们实际上只需要 ID 和名称字段。
如果没有指定 select() 或 fetch(),则查询中不包含 fields 或 _source 部分,ElasticSearch 将返回 _source。
where -> 过滤上下文
添加到 where
的表达式变为 ElasticSearch 筛选器上下文 中的表达式。
筛选器上下文中的表达式不计分,并且不参与相关性排序。筛选器上下文中表达式的优点是它们可以被 ElasticSearch 缓存以提高性能。
默认情况下,where() 表达式通过 MUST
连接
当多个表达式添加到 where()
时,它们默认使用 MUST
添加,这与 AND
的“对象关系”默认值一致。
示例:筛选器上下文
PagedList<Order> orders =
Order.find
.where()
// default to MUST for where()
.customer.name.istartsWith("Rob")
.status.eq(Order.Status.COMPLETE)
.setMaxRows(50)
.setUseDocStore(true)
.findPagedList();
{
"size": 50,
"query": {
"filtered": {
"filter": {
"bool": {
"must": [
{ "prefix": { "customer.name": "rob" } },
{ "term": { "status": "COMPLETE" } }
]
}
}
}
}
}
text -> 查询上下文
添加到 text
的表达式变为 ElasticSearch 查询上下文 中的表达式。这些表达式计分,并用于确定文档的相关性排序。
如果表达式添加到 text()
,则查询自动视为文档存储查询。
默认情况下,text() 表达式通过 SHOULD
连接
当多个表达式添加到 text()
时,它们默认使用 SHOULD
添加,这与 OR
的“对象关系”默认值一致。
示例:查询上下文
PagedList<Order> orders =
Order.find
.text()
// implicitly sets setUseDocStore(true)
// goes to ElasticSearch 'query context'
// defaults to SHOULD for text()
.customer.name.match("Rob")
.status.eq(Order.Status.COMPLETE)
.setMaxRows(50)
.findPagedList();
{
"size": 50,
"query": {
"bool": {
"should": [
{ "match": { "customer.name": "Rob" } },
{ "term": { "status": "COMPLETE" } }
]
}
}
}
示例:查询上下文和筛选器上下文
“全文”查询可以同时具有 查询上下文
和 筛选器上下文
,如下面的示例查询所示。
List<Order> orders = Order.find
.text() // 'query context'
.must()
.customer.name.match("Rob")
.customer.name.match("Bygr")
.endJunction()
.mustNot()
.customer.status.eq(Customer.Status.ACTIVE)
.where() // 'filter context'
.should()
.status.eq(Order.Status.COMPLETE)
.status.isNotNull()
.findList();
{
"query": {
"bool": {
"must": [
{ "match": { "customer.name": "Rob" } },
{ "match": { "customer.name": "Bygr" } }
],
"must_not": [
{ "term": { "customer.status": "ACTIVE" } }
]
}
},
"filter": {
"bool": {
"should": [
{ "term": { "status": "COMPLETE" } },
{ "exists": { "field": "status" } }
]
}
}
}
显式 useDocStore(true)
如果设置了 useDocStore(true)
,则查询将针对 ElasticSearch 执行。
隐式 useDocStore(true)
在以下情况下,查询会隐式设置为文档存储查询
- 使用了
text()
- 使用了文本连接 -
must()
、mustNot()
、should()
- 使用了“全文”表达式 -
match()
、multiMatch()
、textSimple()
、textQueryString()
、textCommonTerms()
必须、不得、应该
MUST
、MUST NOT
和 SHOULD
是在文本搜索中使用的连接表达式,分别映射到 AND
、NOT
和 OR
。
我们不能在正常的 ORM 查询中使用 must()、mustNot() 或 should(),并且一旦我们使用其中一个“文本搜索连接表达式”,查询就会自动被视为文档存储查询,并将命中 ElasticSearch。
Product
.where()
// we used must() so automatically
// becomes a doc store query
.must()
.sku.equalTo("C002")
.findList();
我们使用 must()
、mustNot()
和 should()
来连接表达式。
List<Customer> customers =
server.find(Customer.class)
.text()
.must()
.match("name", "Rob")
.match("smallNote", "interesting")
.findList();
{
"query": {
"bool": {
"must": [
{ "match": { "name": "Rob" } },
{ "match": { "smallNote": "interesting" } }
]
}
}
}
我们使用 endJunction()
来结束“当前连接”,以便我们可以开始另一个连接。
List<Order> orders = Order.find
.text() // 'query context'
.must()
.customer.name.match("Rob")
.customer.name.match("Bygr")
.endJunction()
.mustNot()
.customer.status.eq(Customer.Status.ACTIVE)
.where() // 'filter context'
.should()
.status.eq(Order.Status.COMPLETE)
.status.isNotNull()
.findList();
{
"query": {
"bool": {
"must": [
{ "match": { "customer.name": "Rob" } },
{ "match": { "customer.name": "Bygr" } }
],
"must_not": [
{ "term": { "customer.status": "ACTIVE" } }
]
}
},
"filter": {
"bool": {
"should": [
{ "term": { "status": "COMPLETE" } },
{ "exists": { "field": "status" } }
]
}
}
}
匹配
Match 仅是 ElasticSearch 表达式,在使用时查询会自动视为文档存储查询。
对于查询 Bean,match()
表达式在字符串类型的属性中可用。
List<Order> orders =
new QOrder()
.customer.name.match("Rob")
.findList();
{
"query": {
"match": {
"customer.name": "Rob"
}
}
}
多重匹配、简单文本等
multiMatch()
、textSimple()
、textCommonTerms()
和 textQueryString()
都是仅 ElasticSearch 表达式,使用它们会自动使查询成为文档存储查询。
这些表达式是“查询级别”的表达式,适用于多个字段或整个文档(_all 字段)。
MultiMatch multiMatch =
MultiMatch.fields("customer.name", "customer.notes")
.opAnd()
.type(MultiMatch.Type.PHRASE_PREFIX);
new QOrder()
.multiMatch("Rob", multiMatch)
.findList();
{"query": {
"multi_match": {
"query": "Rob",
"fields": [
"customer.name",
"customer.notes"
],
"type": "phrase_prefix",
"operator": "and"
}
}}
文本表达式
匹配
match
映射到 ElasticSearch 匹配查询。
多重匹配
multi match
映射到 ElasticSearch 多重匹配查询。
简单文本
text simple
映射到 ElasticSearch 简单查询字符串查询。
文本查询字符串
text query string
映射到 ElasticSearch 查询字符串查询。
文本通用术语
text common terms
映射到 ElasticSearch 通用术语查询。