Elasticsearch.Net 使用 NEST 和嵌套对象进行查询以检索文档
Elasticsearch.Net query using NEST and nested objects to retrieve documents
我在应用程序中使用 Elasticsearch.Net 和 NEST,并且在基于嵌套对象 ID 进行搜索时无法访问 Elasticsearch 索引中的文档。数据结构是invoice -> lineItems -> rowItems。我想根据这些 rowItems Id 进行搜索。索引的(简化)映射是:
"invoice": {
"properties": {
"lineItems": {
"properties": {
"accountId": {
"index": "not_analyzed",
"type": "string"
},
"listItems": {
"properties": {
"itemName": {
"analyzer": "str_index_analyzer",
"term_vector": "with_positions_offsets",
"type": "string",
"fields": {
"raw": {
"analyzer": "str_search_analyzer",
"type": "string"
}
}
},
"listItemID": {
"index": "not_analyzed",
"type": "string"
}
}
}
}
}
}
}
当我在 chrome 中对其中一个嵌套对象进行意义搜索时,我可以成功检索到它:
POST /_search
{
"query": {
"bool": {
"should": [
{"match": {
"lineItems.rowItems.rowItemID" : "23f2157f-eb21-400d-b3a1-a61cf1451262"
}}
]
}
}
}
其中 returns 发票类型及其所有详细信息。
我一直在研究使用 NEST 执行此操作的代码,但到目前为止都失败了。我有一个 rowItemId 列表,我想获取与这些 ID 完全匹配的所有发票文档。这是我目前拥有的:
var result = Execute(client => client.Search<Invoice>(s => s
.Aggregations(a => a
.Nested("my_nested_agg", n => n
.Path("lineItems")
.Aggregations(aa => aa
.Filter("my_avg_agg", avg => avg
.Field(p => searchIds.Contains(p.LineItems.First().RowItems.First().TrackingItemID))
)
)
)
)
));
其中 searchIds 是我要搜索的 rowItemId 列表。上面的代码是完全错误的,我不熟悉如何执行此操作的语法。任何帮助将不胜感激。
在您希望跨 对象 属性 的属性进行查询的情况下,需要嵌套类型。鉴于你的例子,
如果您只想在 lineItems
上查询 listItems
的 listItemID
,那么使用 object
type 就可以了。
如果要查询lineItems
上的listItemID
和itemName
,您需要将 listItems
映射为 nested
type.
原因是如果不使用 nested
类型,特定 listItem
的属性之间的关联在索引时不会存储。使用 nested
类型,存储关联(nested
类型在内部存储为文档)。
您在 NEST 中的搜索查询非常相似;在这种情况下,match
查询不需要包含在 bool
查询 should
子句中
var client = new ElasticClient();
var searchResponse = client.Search<Invoice>(s => s
.AllIndices()
.AllTypes()
.Query(q => q
.Match(m => m
.Field(f => f.LineItems.First().ListItems.First().ListItemID)
.Query("23f2157f-eb21-400d-b3a1-a61cf1451262")
)
)
);
获取字段名的lambda表达式就是这样; 获取字段名的表达式.
这会生成查询
POST http://localhost:9200/_search
{
"query": {
"match": {
"lineItems.listItems.listItemID": {
"query": "23f2157f-eb21-400d-b3a1-a61cf1451262"
}
}
}
}
由于 listItemID
是一个 not_analyzed
字符串字段,您可以在此处使用 term
查询,并且您可能不需要计算分数(match 在这种情况下是 true
或 false
),您可以将其包装在 bool
查询 filter
子句中,它可以利用过滤器缓存应该会稍微好一点。
要获取与一组 ID 匹配的文档,我们可以使用 terms
查询
var ids = new[] {
"23f2157f-eb21-400d-b3a1-a61cf1451262",
"23f2157f-eb21-400d-b3a1-a61cf1451263",
"23f2157f-eb21-400d-b3a1-a61cf1451264"
};
var searchResponse = client.Search<Invoice>(s => s
.AllIndices()
.AllTypes()
.Query(q => q
.Terms(m => m
.Field(f => f.LineItems.First().ListItems.First().ListItemID)
.Terms(ids)
)
)
);
最后,shorthand 使用一元 +
运算符
将其包装在 bool
查询 filter
子句中
var searchResponse = client.Search<Invoice>(s => s
.AllIndices()
.AllTypes()
.Query(q => +q
.Terms(m => m
.Field(f => f.LineItems.First().ListItems.First().ListItemID)
.Terms(ids)
)
)
);
我在应用程序中使用 Elasticsearch.Net 和 NEST,并且在基于嵌套对象 ID 进行搜索时无法访问 Elasticsearch 索引中的文档。数据结构是invoice -> lineItems -> rowItems。我想根据这些 rowItems Id 进行搜索。索引的(简化)映射是:
"invoice": {
"properties": {
"lineItems": {
"properties": {
"accountId": {
"index": "not_analyzed",
"type": "string"
},
"listItems": {
"properties": {
"itemName": {
"analyzer": "str_index_analyzer",
"term_vector": "with_positions_offsets",
"type": "string",
"fields": {
"raw": {
"analyzer": "str_search_analyzer",
"type": "string"
}
}
},
"listItemID": {
"index": "not_analyzed",
"type": "string"
}
}
}
}
}
}
}
当我在 chrome 中对其中一个嵌套对象进行意义搜索时,我可以成功检索到它:
POST /_search
{
"query": {
"bool": {
"should": [
{"match": {
"lineItems.rowItems.rowItemID" : "23f2157f-eb21-400d-b3a1-a61cf1451262"
}}
]
}
}
}
其中 returns 发票类型及其所有详细信息。
我一直在研究使用 NEST 执行此操作的代码,但到目前为止都失败了。我有一个 rowItemId 列表,我想获取与这些 ID 完全匹配的所有发票文档。这是我目前拥有的:
var result = Execute(client => client.Search<Invoice>(s => s
.Aggregations(a => a
.Nested("my_nested_agg", n => n
.Path("lineItems")
.Aggregations(aa => aa
.Filter("my_avg_agg", avg => avg
.Field(p => searchIds.Contains(p.LineItems.First().RowItems.First().TrackingItemID))
)
)
)
)
));
其中 searchIds 是我要搜索的 rowItemId 列表。上面的代码是完全错误的,我不熟悉如何执行此操作的语法。任何帮助将不胜感激。
在您希望跨 对象 属性 的属性进行查询的情况下,需要嵌套类型。鉴于你的例子,
如果您只想在
lineItems
上查询listItems
的listItemID
,那么使用object
type 就可以了。如果要查询
lineItems
上的listItemID
和itemName
,您需要将listItems
映射为nested
type.
原因是如果不使用 nested
类型,特定 listItem
的属性之间的关联在索引时不会存储。使用 nested
类型,存储关联(nested
类型在内部存储为文档)。
您在 NEST 中的搜索查询非常相似;在这种情况下,match
查询不需要包含在 bool
查询 should
子句中
var client = new ElasticClient();
var searchResponse = client.Search<Invoice>(s => s
.AllIndices()
.AllTypes()
.Query(q => q
.Match(m => m
.Field(f => f.LineItems.First().ListItems.First().ListItemID)
.Query("23f2157f-eb21-400d-b3a1-a61cf1451262")
)
)
);
获取字段名的lambda表达式就是这样; 获取字段名的表达式.
这会生成查询
POST http://localhost:9200/_search
{
"query": {
"match": {
"lineItems.listItems.listItemID": {
"query": "23f2157f-eb21-400d-b3a1-a61cf1451262"
}
}
}
}
由于 listItemID
是一个 not_analyzed
字符串字段,您可以在此处使用 term
查询,并且您可能不需要计算分数(match 在这种情况下是 true
或 false
),您可以将其包装在 bool
查询 filter
子句中,它可以利用过滤器缓存应该会稍微好一点。
要获取与一组 ID 匹配的文档,我们可以使用 terms
查询
var ids = new[] {
"23f2157f-eb21-400d-b3a1-a61cf1451262",
"23f2157f-eb21-400d-b3a1-a61cf1451263",
"23f2157f-eb21-400d-b3a1-a61cf1451264"
};
var searchResponse = client.Search<Invoice>(s => s
.AllIndices()
.AllTypes()
.Query(q => q
.Terms(m => m
.Field(f => f.LineItems.First().ListItems.First().ListItemID)
.Terms(ids)
)
)
);
最后,shorthand 使用一元 +
运算符
bool
查询 filter
子句中
var searchResponse = client.Search<Invoice>(s => s
.AllIndices()
.AllTypes()
.Query(q => +q
.Terms(m => m
.Field(f => f.LineItems.First().ListItems.First().ListItemID)
.Terms(ids)
)
)
);