将多个短语匹配到 Elastic Search 中的一个字段
Matching multiple phrases to one field in Elastic Search
我用 C# 构建了一个应用程序来搜索我的 Elasticsearch 文档,使用这段代码一切正常....
List<AuditLog> resultsList = Client.SearchAsync<AuditLog>(s => s
.From(0)
.Take(noRows)
.Query(q => q
.Bool(b => b
.Must(mu => mu.MatchPhrase(mp => mp.Field("audit_Event").Query(auditEvents)),
mu => mu.Match(ma => ma.Field(field).Query(value))
)
)
)).Result.Documents.ToList();
一切正常,但有一个新要求,即针对多个短语搜索 audit_Event 字段,例如“用户登录”、“添加员工”等
我找到了对 multi_match 的引用,但这似乎与跨多个字段而不是一个字段中的多个值的搜索更相关。
根据下面的讨论,TermQuery 似乎可以完成这项工作,但 return 没有任何值。有什么想法吗?
QueryContainer queryAnd = new TermQuery() { Field = "audit_Application", Value = "MyApplication" };
QueryContainer queryOr = new TermQuery() { Field = "audit_Event", Value = "Employee Inserted" };
queryOr |= new TermQuery() { Field = "audit_Event", Value = "Employee Updated" };
QueryContainer queryMain = queryAnd & queryOr;
resultsList = Client.SearchAsync<AuditLog>(s => s
.From(0)
.Take(noRows)
.Query(q => q
.Bool(b => b
.Must(queryMain)
)
)).Result.Documents.ToList();
我还使用 Kibana 检查了两个查询,第一个 return 的数据,但第二个没有,现在我想知道数据的索引方式是否有问题。 ..
GET auditlog/_search
{
"query": {
"bool": {
"should": [
{
"match_phrase": {
"audit_Event": "Employee Updated"
}
},
{
"match_phrase": {
"audit_Event": "Employee Inserted"
}
}
]
}
}
}
GET auditlog/_search
{
"query" : {
"terms": {
"audit_Event": ["Employee Updated","Employee Inserted"]
}
}
}
如果要将多个短语与单个字段匹配,则可以使用以下 bool query 与 match_phrase[=12= 的组合]
{
"query": {
"bool": {
"must": [
{
"match_phrase": {
"audit_Event": "User Login"
}
},
{
"match_phrase": {
"audit_Event": "Add Employee"
}
}
]
}
}
}
请试试这个:
QueryContainer queryOr = new MatchPhraseQuery() { Field = "audit_Event", Query = "Employee Inserted" };
queryOr |= new MatchPhraseQuery() { Field = "audit_Event", Query = "Employee Updated" };
ISearchResponse<AuditLog> resultAuditLog = Client.Search<AuditLog>(s => s
.RequestConfiguration(r => r.DisableDirectStreaming())
.From(0)
.Size(100)
.Query(q2 => q2
.Bool(b => b
.Should(queryOr))
)
);
根据您关于 OR
查询按预期工作的说法,下面是您可以使用 NEST
构建查询的方法。您可以根据需要进行任何特定的修改。
这段代码负责触发搜索调用
var searchDescriptor = new SearchDescriptor<AuditLog>()
.Query(q => Blah(auditEventsList))
.From(0)
.Take(noRows);
// other methods you want to chain here
var response = Client.searchAsync<AuditLog>(searchDescriptor);
此处生成搜索查询。请注意 SHOULD
的使用以及对负责动态生成 match_phrase
查询的另一个方法的调用。
private static QueryContainer Blah(List<string> auditEventsList)
{
return new QueryContainerDescriptor<AuditLog>().Bool(
b => b.Should(
InnerBlah(auditEventsList)
)
);
}
此方法生成一个包含 match_phrase
个查询的数组,这些查询将传递给上述代码段中的 should
。这些是通过迭代接收到的所有审计事件生成的。
private static QueryContainer[] InnerBlah(List<string> auditEventsList)
{
QueryContainer orQuery = null;
List<QueryContainer> queryContainerList = new List<QueryContainer>();
foreach(var item in auditEventsList)
{
orQuery = new MatchPhraseQuery { Field = "audit_Event", Query = item };
queryContainerList.Add(orQuery);
}
return queryContainerList.ToArray();
}
我用 C# 构建了一个应用程序来搜索我的 Elasticsearch 文档,使用这段代码一切正常....
List<AuditLog> resultsList = Client.SearchAsync<AuditLog>(s => s
.From(0)
.Take(noRows)
.Query(q => q
.Bool(b => b
.Must(mu => mu.MatchPhrase(mp => mp.Field("audit_Event").Query(auditEvents)),
mu => mu.Match(ma => ma.Field(field).Query(value))
)
)
)).Result.Documents.ToList();
一切正常,但有一个新要求,即针对多个短语搜索 audit_Event 字段,例如“用户登录”、“添加员工”等
我找到了对 multi_match 的引用,但这似乎与跨多个字段而不是一个字段中的多个值的搜索更相关。
根据下面的讨论,TermQuery 似乎可以完成这项工作,但 return 没有任何值。有什么想法吗?
QueryContainer queryAnd = new TermQuery() { Field = "audit_Application", Value = "MyApplication" };
QueryContainer queryOr = new TermQuery() { Field = "audit_Event", Value = "Employee Inserted" };
queryOr |= new TermQuery() { Field = "audit_Event", Value = "Employee Updated" };
QueryContainer queryMain = queryAnd & queryOr;
resultsList = Client.SearchAsync<AuditLog>(s => s
.From(0)
.Take(noRows)
.Query(q => q
.Bool(b => b
.Must(queryMain)
)
)).Result.Documents.ToList();
我还使用 Kibana 检查了两个查询,第一个 return 的数据,但第二个没有,现在我想知道数据的索引方式是否有问题。 ..
GET auditlog/_search
{
"query": {
"bool": {
"should": [
{
"match_phrase": {
"audit_Event": "Employee Updated"
}
},
{
"match_phrase": {
"audit_Event": "Employee Inserted"
}
}
]
}
}
}
GET auditlog/_search
{
"query" : {
"terms": {
"audit_Event": ["Employee Updated","Employee Inserted"]
}
}
}
如果要将多个短语与单个字段匹配,则可以使用以下 bool query 与 match_phrase[=12= 的组合]
{
"query": {
"bool": {
"must": [
{
"match_phrase": {
"audit_Event": "User Login"
}
},
{
"match_phrase": {
"audit_Event": "Add Employee"
}
}
]
}
}
}
请试试这个:
QueryContainer queryOr = new MatchPhraseQuery() { Field = "audit_Event", Query = "Employee Inserted" };
queryOr |= new MatchPhraseQuery() { Field = "audit_Event", Query = "Employee Updated" };
ISearchResponse<AuditLog> resultAuditLog = Client.Search<AuditLog>(s => s
.RequestConfiguration(r => r.DisableDirectStreaming())
.From(0)
.Size(100)
.Query(q2 => q2
.Bool(b => b
.Should(queryOr))
)
);
根据您关于 OR
查询按预期工作的说法,下面是您可以使用 NEST
构建查询的方法。您可以根据需要进行任何特定的修改。
这段代码负责触发搜索调用
var searchDescriptor = new SearchDescriptor<AuditLog>()
.Query(q => Blah(auditEventsList))
.From(0)
.Take(noRows);
// other methods you want to chain here
var response = Client.searchAsync<AuditLog>(searchDescriptor);
此处生成搜索查询。请注意 SHOULD
的使用以及对负责动态生成 match_phrase
查询的另一个方法的调用。
private static QueryContainer Blah(List<string> auditEventsList)
{
return new QueryContainerDescriptor<AuditLog>().Bool(
b => b.Should(
InnerBlah(auditEventsList)
)
);
}
此方法生成一个包含 match_phrase
个查询的数组,这些查询将传递给上述代码段中的 should
。这些是通过迭代接收到的所有审计事件生成的。
private static QueryContainer[] InnerBlah(List<string> auditEventsList)
{
QueryContainer orQuery = null;
List<QueryContainer> queryContainerList = new List<QueryContainer>();
foreach(var item in auditEventsList)
{
orQuery = new MatchPhraseQuery { Field = "audit_Event", Query = item };
queryContainerList.Add(orQuery);
}
return queryContainerList.ToArray();
}