elasticsearch必须与子查询相交

zlhcx6iw  于 2021-06-10  发布在  ElasticSearch
关注(0)|答案(1)|浏览(376)

我想执行一个elasticsearch查询,它结合了两个子查询(and operator),每个子查询在不同的字段(or operator)中搜索。
例如,如果我传递“name”参数,它只在name字段(firstname+lastname)中搜索,如果我传递“contact”参数,它在contact字段(contactemail+contacttelephone)中搜索。
下面的代码返回:
如果name为null但提供了contact,则返回所有结果(应仅返回正确的部分)
如果contact为null但提供了name,则返回所有结果(应仅返回左侧部分)
联合结果(或运算符),如果提供了名称和联系人值(应返回left intersect right)

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 因为我想要相关的分数。
我认为有两个问题:应用and而不是or,如果条件为空则忽略子查询。你知道吗?

7bsow1i6

7bsow1i61#

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 或者 contactnull ,则该查询将被忽略。例如,设置 namenull ```
string name = null;

var response = client.Search(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"
}
}
]
}
}
}

这利用了一种称为无条件查询的客户机功能—如果某个查询的某个组件在不应为空时为空,则该特定查询将被视为无条件查询,以便形成一个完整的查询。例如,对于 `multi_match` 如果 `Query` 是 `null` ![](https://i.stack.imgur.com/yHfJr.png)
无条件查询的目的是使编写更复杂的查询更容易,并且可以通过指定 `Verbatim()` 在查询上。然而,由于它们违背了最小意外的原则,因此有人打算在将来删除它们。在不依赖无条件行为的情况下执行相同的查询

var response = client.Search(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)
                    );
            }
        )
    )
)

);

相关问题