弹性搜索中function_score的语法

时间:2014-02-26 10:51:40

标签: elasticsearch

我是Elastic Search的新手。我已经在ElasticSearch中为电影艺术家(演员和导演)编制索引,并且简单的文本搜索工作正常,例如,如果我使用以下语法搜索'steven'

{"query":
    {"query_string":
        {"query":"steven"}
    }
}

...我得到以下结果,这很好:

1. Steven Conrad       - Popularity (from document) = 487 - elasticsearch _score = 3,2589545
2. Steven Knight       - Popularity (from document) = 487 - elasticsearch _score = 3,076738
3. Steven Waddington   - Popularity (from document) = 431 - elasticsearch _score = 2,4931839
4. Steven E. De Souza  - Popularity (from document) = 534 - elasticsearch _score = 2,4613905
5. Steven R. Monroe    - Popularity (from document) = 293 - elasticsearch _score = 2,4613905
6. Steven Mackintosh   - Popularity (from document) = 363 - elasticsearch _score = 2,2812681
7. Steven Wright       - Popularity (from document) = 356 - elasticsearch _score = 2,2812681
8. Steven Soderbergh   - Popularity (from document) = 5947 - elasticsearch _score = 2,270944
9. Steven Seagal       - Popularity (from document) = 1388 - elasticsearch _score = 2,270944
10. Steven Bauer        - Popularity (from document) = 714 - elasticsearch _score = 2,270944

但是,正如您在上面所看到的,我的文档中有一个受欢迎的数字字段,并且在搜索“ steven ”时,我想要最受欢迎艺术家(Steven Soderbergh,Steven Seagal ......)先来。

理想情况下,我想按popularity * _score

对上述结果进行排序

我很确定我必须使用弹性搜索的function_score功能,但我无法弄清楚确切的语法。

我尝试使用以下语法

进行“改进”搜索
{
  "query": {
    "custom_score": {
      "query": {
        "query_string": {
          "query": "steven"
        }
      },
      "script": "_score * doc['popularity']"
    }
  }
}

但是我得到了一个例外(从以下错误信息中提取:)

org.elasticsearch.search.query.QueryPhaseExecutionException: [my_index][4]: query[filtered(function score (_all:steven,function=script[_score * doc['popularity']], params [null]))->cache(_type:artist)],from[0],size[10]: Query Failed [Failed to execute main query]
  // ....
Caused by: java.lang.RuntimeException: uncomparable values <<1.9709579>> and <<org.elasticsearch.index.fielddata.ScriptDocValues$Longs@7c5b73bc>>
  // ... 
  ... 9 more
Caused by: java.lang.ClassCastException: org.elasticsearch.index.fielddata.ScriptDocValues$Longs cannot be cast to java.lang.Float
  at java.lang.Float.compareTo(Float.java:33)
  at org.elasticsearch.common.mvel2.math.MathProcessor.doOperationNonNumeric(MathProcessor.java:266)

我觉得我使用的语法不正确

什么是正确的语法?或者还有其他我缺少的东西?提前多多感谢

修改 我的表映射定义如下:

"mappings" : {
  "artist" : {
    "_all" : {
      "auto_boost" : true
    },
    "properties" : {
      "first_name" : {
        "type" : "string",
        "index" : "not_analyzed",
        "analyzer" : "standard"
      },
      "last_name" : {
        "type" : "string",
        "boost" : 2.0,
        "index" : "not_analyzed",
        "norms" : {
          "enabled" : true
        },
        "analyzer" : "standard"
      },
      "popularity" : {
        "type" : "integer"
      }
    }
  }
}

1 个答案:

答案 0 :(得分:7)

你错过了.value附近的doc['...']吗?

这适用于我(我存储的整数没有映射):

$ curl -XPUT localhost:9200/test/test/a -d '{"name":"steven", "popularity": 666}'
{"_index":"test","_type":"test","_id":"a","_version":1,"created":true}

$ curl -XPUT localhost:9200/test/test/b -d '{"name":"steven", "popularity": 42}' 
{"_index":"test","_type":"test","_id":"b","_version":1,"created":true}

$ curl -XPOST localhost:9200/test/test/_search\?pretty -d '{ "query": { "custom_score": { "query": { "match_all": {}}, "script": "_score * doc[\"popularity\"].value" } } }'                                                                                                                                                 
{
  "took" : 83,
  "timed_out" : false,
  "_shards" : {
    "total" : 1,
    "successful" : 1,
    "failed" : 0
  },
  "hits" : {
    "total" : 2,
    "max_score" : 666.0,
    "hits" : [ {
      "_index" : "test",
      "_type" : "test",
      "_id" : "a",
      "_score" : 666.0, "_source" : {"name":"steven", "popularity": 666}
    }, {
      "_index" : "test",
      "_type" : "test",
      "_id" : "b",
      "_score" : 42.0, "_source" : {"name":"steven", "popularity": 42}
    } ]
  }
}