如何使用 C# NEST 在 ElasticSearch 中搜索数组的动态元素?
How to search dynamic elements of array in ElasticSearch using C# NEST?
我的 elasticsearch 中有这种结构的这些数据。
如何从此数组中搜索名字、中间名和姓氏?注意:NameDetails
数组长度是动态的。 A 可能只有 NameDetails
中的一个元素。 B 可以有 3 个元素 NameDetails
.
目前只能按gender
搜索。我正在使用 NEST nuget C#。这是我的查询。
var response = await _elasticClient.SearchAsync<Person>(s => s
.Query(q => q
.Bool(b => b.Must(
mu => mu
.Match(m => m
.Field(f => f.Gender)
.Query(Gender)
)
)
)
)
);
在 NEST 中,我尝试使用此代码但 return 没有结果。
var response = _elasticClient.Search <Model.Entities.Split.Person.Person> (s => s
.Index("person")
.Query(q => q
.Match(m => m
.Field(f => f.NameDetails.Name[0].NameValue.FirstName)
.Query("Fawsu")
)
)
);
但是如果我直接 运行 ElasticSearch 的 DSL 查询和下面的查询,它 return 的结果。
GET /person/_search
{
"query": {
"match": {
"nameDetails.nameValue.firstName": {
"query": "Fawsu"
}
}
}
}
}
或
GET /person/_search
{
"query": {
"bool": {
"must": [
{
"fuzzy": {
"nameDetails.nameValue.surname": {
"value": "Pibba",
"fuzziness": "AUTO"
}
}
},
{
"fuzzy": {
"nameDetails.nameValue.firstName": {
"value": "Fawsu",
"fuzziness": "AUTO"
}
}
}
]
}
}
}
如果你想搜索类似的东西:
名字 ==“约翰”AND 中间名 ==“本”AND 姓氏 ==“史密斯”
然后你可以使用TermQuery搜索firstName
、middleName
和lastName
:
我更熟悉对象初始化语法(需要using static Nest.Infer
)
using static Nest.Infer;
var query = new TermQuery
{
Name = "my firstName query",
Field = Field<Person>(p => p.firstName),
Value = "John"
};
您需要为 middleName
和 lastName
编写 2 个查询,然后 AND
所有这些查询。
如果你想搜索类似的东西:
firstName == "John" OR middleName == "John" OR lastName == "John"
那么你可以使用Multi-match Query:
using static Nest.Infer;
var query = new MultiMatchQuery
{
Name = "My Multi-match query",
Fields = Field<Person>(p => p.firstName, 1.1) // 1.1 is boost (default is 1)
.And<AdDocument>(p => p.middleName, 1)
.And<AdDocument>(p => p.lastName, 1)
Query = "John"
//Fuzziness = Fuzziness.Auto
};
了解它如何映射到 POCO 很有用
public class Person
{
public string Gender { get; set; }
public string ActiveStatus { get; set; }
public string Deceased { get; set; }
public List<Name> NameDetails { get; set; }
}
public class Name
{
public List<NameValue> NameValue { get; set; }
public string NameType { get; set; }
}
public class NameValue
{
public string FirstName { get; set; }
public string MiddleName { get; set; }
public string LastName { get; set; }
}
(您可以将其中一些字段映射为字符串以外的类型,我将把它留作 reader 的练习)。
搜索名字
var client = new ElasticClient();
var response = client.Search<Person>(s => s
.Index("people")
.Query(q => q
.Match(m => m
.Field(f => f.NameDetails[0].NameValue[0].FirstName)
.Query("Fawsu")
)
)
);
产生查询
POST http://localhost:9200/people/_search?pretty=true&typed_keys=true
{
"query": {
"match": {
"nameDetails.nameValue.firstName": {
"query": "Fawsu"
}
}
}
}
.Field(f => f...)
中的表达式是构建到 "nameDetails.nameValue.firstName"
路径的表达式,它将在 any 中查找名称值的匹配项和名称详细信息。它使用索引器的事实 而不是 意味着它以名字详细信息的名字值为目标,但这只是一种遍历对象图以构建表达式的方法。
要构建复合查询以针对 相同 名称值的多个值,Name
和 NameValue
都需要 mapped as nested
data types,然后会使用嵌套查询。
对于单个字段
var response = client.Search<Person>(s => s
.Index("people")
.Query(q => q
.Nested(n => n
.Path(f => f.NameDetails)
.Query(nq => nq
.Nested(nn => nn
.Path(f => f.NameDetails[0].NameValue)
.Query(nnq => nnq
.Match(m => m
.Field(f => f.NameDetails[0].NameValue[0].FirstName)
.Query("Fawsu")
)
)
)
)
)
)
);
对于多个字段
var response = client.Search<Person>(s => s
.Index("people")
.Query(q => q
.Nested(n => n
.Path(f => f.NameDetails)
.Query(nq => nq
.Nested(nn => nn
.Path(f => f.NameDetails[0].NameValue)
.Query(nnq => nnq
.Bool(b => b
.Must(m => m
.Match(m => m
.Field(f => f.NameDetails[0].NameValue[0].FirstName)
.Query("Fawsu")
), m => m
.Match(m => m
.Field(f => f.NameDetails[0].NameValue[0].LastName)
.Query("Pibba")
)
)
)
)
)
)
)
)
);
后者导致查询
POST http://localhost:9200/people/_search?pretty=true&typed_keys=true
{
"query": {
"nested": {
"path": "nameDetails",
"query": {
"nested": {
"path": "nameDetails.nameValue",
"query": {
"bool": {
"must": [
{
"match": {
"nameDetails.nameValue.firstName": {
"query": "Fawsu"
}
}
},
{
"match": {
"nameDetails.nameValue.lastName": {
"query": "Pibba"
}
}
}
]
}
}
}
}
}
}
}
我的 elasticsearch 中有这种结构的这些数据。
如何从此数组中搜索名字、中间名和姓氏?注意:NameDetails
数组长度是动态的。 A 可能只有 NameDetails
中的一个元素。 B 可以有 3 个元素 NameDetails
.
目前只能按gender
搜索。我正在使用 NEST nuget C#。这是我的查询。
var response = await _elasticClient.SearchAsync<Person>(s => s
.Query(q => q
.Bool(b => b.Must(
mu => mu
.Match(m => m
.Field(f => f.Gender)
.Query(Gender)
)
)
)
)
);
在 NEST 中,我尝试使用此代码但 return 没有结果。
var response = _elasticClient.Search <Model.Entities.Split.Person.Person> (s => s
.Index("person")
.Query(q => q
.Match(m => m
.Field(f => f.NameDetails.Name[0].NameValue.FirstName)
.Query("Fawsu")
)
)
);
但是如果我直接 运行 ElasticSearch 的 DSL 查询和下面的查询,它 return 的结果。
GET /person/_search
{
"query": {
"match": {
"nameDetails.nameValue.firstName": {
"query": "Fawsu"
}
}
}
}
}
或
GET /person/_search
{
"query": {
"bool": {
"must": [
{
"fuzzy": {
"nameDetails.nameValue.surname": {
"value": "Pibba",
"fuzziness": "AUTO"
}
}
},
{
"fuzzy": {
"nameDetails.nameValue.firstName": {
"value": "Fawsu",
"fuzziness": "AUTO"
}
}
}
]
}
}
}
如果你想搜索类似的东西:
名字 ==“约翰”AND 中间名 ==“本”AND 姓氏 ==“史密斯”
然后你可以使用TermQuery搜索firstName
、middleName
和lastName
:
我更熟悉对象初始化语法(需要using static Nest.Infer
)
using static Nest.Infer;
var query = new TermQuery
{
Name = "my firstName query",
Field = Field<Person>(p => p.firstName),
Value = "John"
};
您需要为 middleName
和 lastName
编写 2 个查询,然后 AND
所有这些查询。
如果你想搜索类似的东西:
firstName == "John" OR middleName == "John" OR lastName == "John"
那么你可以使用Multi-match Query:
using static Nest.Infer;
var query = new MultiMatchQuery
{
Name = "My Multi-match query",
Fields = Field<Person>(p => p.firstName, 1.1) // 1.1 is boost (default is 1)
.And<AdDocument>(p => p.middleName, 1)
.And<AdDocument>(p => p.lastName, 1)
Query = "John"
//Fuzziness = Fuzziness.Auto
};
了解它如何映射到 POCO 很有用
public class Person
{
public string Gender { get; set; }
public string ActiveStatus { get; set; }
public string Deceased { get; set; }
public List<Name> NameDetails { get; set; }
}
public class Name
{
public List<NameValue> NameValue { get; set; }
public string NameType { get; set; }
}
public class NameValue
{
public string FirstName { get; set; }
public string MiddleName { get; set; }
public string LastName { get; set; }
}
(您可以将其中一些字段映射为字符串以外的类型,我将把它留作 reader 的练习)。
搜索名字
var client = new ElasticClient();
var response = client.Search<Person>(s => s
.Index("people")
.Query(q => q
.Match(m => m
.Field(f => f.NameDetails[0].NameValue[0].FirstName)
.Query("Fawsu")
)
)
);
产生查询
POST http://localhost:9200/people/_search?pretty=true&typed_keys=true
{
"query": {
"match": {
"nameDetails.nameValue.firstName": {
"query": "Fawsu"
}
}
}
}
.Field(f => f...)
中的表达式是构建到 "nameDetails.nameValue.firstName"
路径的表达式,它将在 any 中查找名称值的匹配项和名称详细信息。它使用索引器的事实 而不是 意味着它以名字详细信息的名字值为目标,但这只是一种遍历对象图以构建表达式的方法。
要构建复合查询以针对 相同 名称值的多个值,Name
和 NameValue
都需要 mapped as nested
data types,然后会使用嵌套查询。
对于单个字段
var response = client.Search<Person>(s => s
.Index("people")
.Query(q => q
.Nested(n => n
.Path(f => f.NameDetails)
.Query(nq => nq
.Nested(nn => nn
.Path(f => f.NameDetails[0].NameValue)
.Query(nnq => nnq
.Match(m => m
.Field(f => f.NameDetails[0].NameValue[0].FirstName)
.Query("Fawsu")
)
)
)
)
)
)
);
对于多个字段
var response = client.Search<Person>(s => s
.Index("people")
.Query(q => q
.Nested(n => n
.Path(f => f.NameDetails)
.Query(nq => nq
.Nested(nn => nn
.Path(f => f.NameDetails[0].NameValue)
.Query(nnq => nnq
.Bool(b => b
.Must(m => m
.Match(m => m
.Field(f => f.NameDetails[0].NameValue[0].FirstName)
.Query("Fawsu")
), m => m
.Match(m => m
.Field(f => f.NameDetails[0].NameValue[0].LastName)
.Query("Pibba")
)
)
)
)
)
)
)
)
);
后者导致查询
POST http://localhost:9200/people/_search?pretty=true&typed_keys=true
{
"query": {
"nested": {
"path": "nameDetails",
"query": {
"nested": {
"path": "nameDetails.nameValue",
"query": {
"bool": {
"must": [
{
"match": {
"nameDetails.nameValue.firstName": {
"query": "Fawsu"
}
}
},
{
"match": {
"nameDetails.nameValue.lastName": {
"query": "Pibba"
}
}
}
]
}
}
}
}
}
}
}