Elasticsearch 必须与子查询相交
Elasticsearch must with subquery intersection
我想执行一个结合了两个子查询(AND 运算符)的 Elasticsearch 查询,每个子查询都在不同的字段中搜索(OR 运算符)。
例如,如果我传递“姓名”参数,它只会在姓名字段(名字 + 姓氏)中搜索,如果我传递“联系人”参数,它会在联系人字段(ContactEmail + ContactTelephone)中搜索。
下面的代码return:
- 如果名称为空但提供了联系方式,则所有结果(应仅 return 右侧部分)
- 如果联系人为空但提供了名称,则所有结果(应该只 return 左侧部分)
- 联合结果(OR 运算符)如果提供了姓名和联系人值(应该 return 左相交右)
searchQuery = searchQuery
.MinScore(minScore)
.Query(qu => qu
.Bool(b => b
.Must(m => m
.MultiMatch(mm=> mm
.Fields(fs=> fs
.Field(f => f.Firstname)
.Field(f => f.Lastname)
)
.Query(name)
.Operator(Operator.Or)
)
)
.Must(m => m
.MultiMatch(mm => mm
.Fields(fs => fs
.Field(f => f.ContactEmail)
.Field(f => f.ContactTelephone)
)
.Query(contact)
.Operator(Operator.Or)
)
)
)
);
我正在使用 Must
因为我想要关联的分数。
我认为有 2 个问题:应用 AND 而不是 OR 以及如果条件为空则忽略子查询。有什么想法吗?
must 子句中的两个查询 必须 是同一个 .Must()
调用的一部分。
鉴于以下 POCO
public class Person
{
public string Firstname { get; set; }
public string Lastname { get; set; }
public string ContactEmail {get;set;}
public string ContactTelephone {get;set;}
}
查询应如下所示
var client = new ElasticClient(settings);
var minScore = 2;
string name = "name";
string contact = "contact";
var response = client.Search<Person>(s => s
.MinScore(minScore)
.Query(qu => qu
.Bool(b => b
.Must(m => m
.MultiMatch(mm => mm
.Fields(fs => fs
.Field(f => f.Firstname)
.Field(f => f.Lastname)
)
.Query(name)
.Operator(Operator.Or)
), m => m
.MultiMatch(mm => mm
.Fields(fs => fs
.Field(f => f.ContactEmail)
.Field(f => f.ContactTelephone)
)
.Query(contact)
.Operator(Operator.Or)
)
)
)
)
);
产生以下结果
{
"min_score": 2.0,
"query": {
"bool": {
"must": [
{
"multi_match": {
"fields": [
"contactEmail",
"contactTelephone"
],
"operator": "or",
"query": "contact"
}
}
]
}
}
}
如果 name
或 contact
是 null
,则该查询将被忽略。例如,将 name
设置为 null
string name = null;
var response = client.Search<Person>(s => s
.MinScore(minScore)
.Query(qu => qu
.Bool(b => b
.Must(m => m
.MultiMatch(mm => mm
.Fields(fs => fs
.Field(f => f.Firstname)
.Field(f => f.Lastname)
)
.Query(name)
.Operator(Operator.Or)
), m => m
.MultiMatch(mm => mm
.Fields(fs => fs
.Field(f => f.ContactEmail)
.Field(f => f.ContactTelephone)
)
.Query(contact)
.Operator(Operator.Or)
)
)
)
)
);
产量
{
"min_score": 2.0,
"query": {
"bool": {
"must": [
{
"multi_match": {
"fields": [
"contactEmail",
"contactTelephone"
],
"operator": "or",
"query": "contact"
}
}
]
}
}
}
这利用了称为 无条件查询 的客户端功能 - 如果查询的某个组成部分为 空[=51,则特定查询被认为是无条件的=] 当它不应该时,为了形成一个完整的查询。例如,for a multi_match
query, it is considered to be conditionless if the Query
is null
无条件查询的目的是让编写更复杂的查询变得更容易,the behaviour can be bypassed by specifying Verbatim()
on the query. Since they go against the principle of least surprise however, there is an intention to remove them in the future。在不依赖无条件行为的情况下执行相同的查询
var response = client.Search<Person>(s => s
.MinScore(minScore)
.Query(qu => qu
.Bool(b => b
.Must(m =>
{
if (name == null)
return m;
return m
.MultiMatch(mm => mm
.Fields(fs => fs
.Field(f => f.Firstname)
.Field(f => f.Lastname)
)
.Query(name)
.Operator(Operator.Or)
);
}, m =>
{
if (contact == null)
return m;
return m
.MultiMatch(mm => mm
.Fields(fs => fs
.Field(f => f.ContactEmail)
.Field(f => f.ContactTelephone)
)
.Query(contact)
.Operator(Operator.Or)
);
}
)
)
)
);
我想执行一个结合了两个子查询(AND 运算符)的 Elasticsearch 查询,每个子查询都在不同的字段中搜索(OR 运算符)。
例如,如果我传递“姓名”参数,它只会在姓名字段(名字 + 姓氏)中搜索,如果我传递“联系人”参数,它会在联系人字段(ContactEmail + ContactTelephone)中搜索。
下面的代码return:
- 如果名称为空但提供了联系方式,则所有结果(应仅 return 右侧部分)
- 如果联系人为空但提供了名称,则所有结果(应该只 return 左侧部分)
- 联合结果(OR 运算符)如果提供了姓名和联系人值(应该 return 左相交右)
searchQuery = searchQuery
.MinScore(minScore)
.Query(qu => qu
.Bool(b => b
.Must(m => m
.MultiMatch(mm=> mm
.Fields(fs=> fs
.Field(f => f.Firstname)
.Field(f => f.Lastname)
)
.Query(name)
.Operator(Operator.Or)
)
)
.Must(m => m
.MultiMatch(mm => mm
.Fields(fs => fs
.Field(f => f.ContactEmail)
.Field(f => f.ContactTelephone)
)
.Query(contact)
.Operator(Operator.Or)
)
)
)
);
我正在使用 Must
因为我想要关联的分数。
我认为有 2 个问题:应用 AND 而不是 OR 以及如果条件为空则忽略子查询。有什么想法吗?
must 子句中的两个查询 必须 是同一个 .Must()
调用的一部分。
鉴于以下 POCO
public class Person
{
public string Firstname { get; set; }
public string Lastname { get; set; }
public string ContactEmail {get;set;}
public string ContactTelephone {get;set;}
}
查询应如下所示
var client = new ElasticClient(settings);
var minScore = 2;
string name = "name";
string contact = "contact";
var response = client.Search<Person>(s => s
.MinScore(minScore)
.Query(qu => qu
.Bool(b => b
.Must(m => m
.MultiMatch(mm => mm
.Fields(fs => fs
.Field(f => f.Firstname)
.Field(f => f.Lastname)
)
.Query(name)
.Operator(Operator.Or)
), m => m
.MultiMatch(mm => mm
.Fields(fs => fs
.Field(f => f.ContactEmail)
.Field(f => f.ContactTelephone)
)
.Query(contact)
.Operator(Operator.Or)
)
)
)
)
);
产生以下结果
{
"min_score": 2.0,
"query": {
"bool": {
"must": [
{
"multi_match": {
"fields": [
"contactEmail",
"contactTelephone"
],
"operator": "or",
"query": "contact"
}
}
]
}
}
}
如果 name
或 contact
是 null
,则该查询将被忽略。例如,将 name
设置为 null
string name = null;
var response = client.Search<Person>(s => s
.MinScore(minScore)
.Query(qu => qu
.Bool(b => b
.Must(m => m
.MultiMatch(mm => mm
.Fields(fs => fs
.Field(f => f.Firstname)
.Field(f => f.Lastname)
)
.Query(name)
.Operator(Operator.Or)
), m => m
.MultiMatch(mm => mm
.Fields(fs => fs
.Field(f => f.ContactEmail)
.Field(f => f.ContactTelephone)
)
.Query(contact)
.Operator(Operator.Or)
)
)
)
)
);
产量
{
"min_score": 2.0,
"query": {
"bool": {
"must": [
{
"multi_match": {
"fields": [
"contactEmail",
"contactTelephone"
],
"operator": "or",
"query": "contact"
}
}
]
}
}
}
这利用了称为 无条件查询 的客户端功能 - 如果查询的某个组成部分为 空[=51,则特定查询被认为是无条件的=] 当它不应该时,为了形成一个完整的查询。例如,for a multi_match
query, it is considered to be conditionless if the Query
is null
无条件查询的目的是让编写更复杂的查询变得更容易,the behaviour can be bypassed by specifying Verbatim()
on the query. Since they go against the principle of least surprise however, there is an intention to remove them in the future。在不依赖无条件行为的情况下执行相同的查询
var response = client.Search<Person>(s => s
.MinScore(minScore)
.Query(qu => qu
.Bool(b => b
.Must(m =>
{
if (name == null)
return m;
return m
.MultiMatch(mm => mm
.Fields(fs => fs
.Field(f => f.Firstname)
.Field(f => f.Lastname)
)
.Query(name)
.Operator(Operator.Or)
);
}, m =>
{
if (contact == null)
return m;
return m
.MultiMatch(mm => mm
.Fields(fs => fs
.Field(f => f.ContactEmail)
.Field(f => f.ContactTelephone)
)
.Query(contact)
.Operator(Operator.Or)
);
}
)
)
)
);