鉴于以下索引,如何在嵌套数组中选择适当的项并访问其中一个值?这里的目的是在system
内的值中使用它。
script_score
我的查询按技巧_id过滤,效果很好。然后,我希望能够使用# Create mapping
curl -XPUT localhost:9200/test/user/_mapping -d '
{
"user" : {
"properties" : {
"name" : {
"type" : "string"
},
"skills" : {
"type": "nested",
"properties" : {
"skill_id" : {
"type" : "integer"
},
"recommendations_count" : {
"type" : "integer"
}
}
}
}
}
}
'
# Indexing Data
curl -XPUT localhost:9200/test/user/1 -d '
{
"name": "John",
"skills": [
{
"skill_id": 100,
"recommendations_count": 5
},
{
"skill_id": 200,
"recommendations_count": 3
}
]
}
'
curl -XPUT localhost:9200/test/user/2 -d '
{
"name": "Mary",
"skills": [
{
"skill_id": 100,
"recommendations_count": 9
},
{
"skill_id": 200,
"recommendations_count": 0
}
]
}
'
来提高script_score
个文档的分数,并为给定的skill_id提高user
。(< - 这是关键)。
recommendations_count
如何从curl -XPOST localhost:9200/test/user/_search -d '
{
"query":{
"function_score":{
"query":{
"bool":{
"must":{
"nested":{
"path":"skills",
"query":{
"bool":{
"must":{
"term":{
"skill_id":100
}
}
}
}
}
}
}
},
"functions":[
{
"script_score": {
"script": "sqrt(1.2 * doc['skills.recommendations_count'].value)"
}
}
]
}
}
}
}
'
中访问skills
数组,找到' skill_id:100'数组中的项,然后使用其script
值?上面的recommendations_count
目前无效(无论数据如何,得分始终为0,因此我认为script_score
没有找到正确的位置。
答案 0 :(得分:6)
对于您的特定问题,脚本需要嵌套上下文,就像您使用term
查询一样。
这可以为ES 1.x重写:
curl -XGET 'localhost:9200/test/_search' -d'
{
"query": {
"nested": {
"path": "skills",
"query": {
"filtered": {
"filter": {
"term": {
"skills.skill_id": 100
}
},
"query": {
"function_score": {
"functions": [
{
"script_score": {
"script": "sqrt(1.2 * doc['skills.recommendations_count'].value)"
}
}
]
}
}
}
}
}
}
}'
对于ES 2.x(过滤器成为ES 2.x中的一等公民,因此语法有所改变以便赶上!):
curl -XGET 'localhost:9200/test/_search' -d'
{
"query": {
"nested": {
"path": "skills",
"query": {
"bool": {
"filter": {
"term": {
"skills.skill_id": 100
}
},
"must": {
"function_score": {
"functions": [
{
"script_score": {
"script": "sqrt(1.2 * doc['skills.recommendations_count'].value)"
}
}
]
}
}
}
}
}
}
}'
注意:我将term
查询设为term
过滤器,因为它对分数没有任何逻辑影响(它是完全匹配与否)。我还将嵌套字段的名称添加到term
过滤器中,这是Elasticsearch 2.x及更高版本(以及之前的良好实践)中的一项要求。
如果不这样做,你可以(和应该)尽可能避免使用脚本。这是其中一个案例。 function_score
supports the concept of a field_value_factor
function that lets you do things exactly like you are trying, but entirely without a script。您还可以选择提供“缺失”值,以控制在缺少字段时发生的情况。
这转换为完全相同的脚本,但它会表现得更好:
curl -XGET 'localhost:9200/test/_search' -d'
{
"query": {
"nested": {
"path": "skills",
"query": {
"filtered": {
"filter": {
"term": {
"skills.skill_id": 100
}
},
"query": {
"function_score": {
"functions": [
{
"field_value_factor": {
"field": "skills.recommendations_count",
"factor": 1.2,
"modifier": "sqrt",
"missing": 0
}
}
]
}
}
}
}
}
}
}'
对于ES 2.x:
curl -XGET 'localhost:9200/test/_search' -d'
{
"query": {
"nested": {
"path": "skills",
"query": {
"bool": {
"filter": {
"term": {
"skills.skill_id": 100
}
},
"must": {
"function_score": {
"functions": [
{
"field_value_factor": {
"field": "skills.recommendations_count",
"factor": 1.2,
"modifier": "sqrt",
"missing": 0
}
}
]
}
}
}
}
}
}
}'
脚本很慢且they also imply the use of fielddata in Elasticsearch 1.x, which is bad。你确实提到了doc值,这是一个很有希望的开始,表明使用Elasticsearch 2.x,但这可能只是术语。
如果您刚开始使用Elasticsearch,我强烈建议您从最新版本开始。