使用field_value_factor在非现有字段上进行功能评分查询

时间:2014-12-03 14:30:04

标签: java elasticsearch scoring

我已经在这个问题上搞砸了很长一段时间了,而且无法解决这个问题。

采取以下案例:

我公司有2名员工,他们有自己的博客页面:

POST blog/page/1
{
  "author": "Byron",
  "author-title": "Junior Software Developer",
  "content" : "My amazing bio"
}

POST blog/page/2
{
  "author": "Jason",
  "author-title": "Senior Software Developer",
  "content" : "My amazing bio is better"
}

在他们创建博客帖子之后,我们希望跟踪他们的观看次数'他们的博客并根据他们的观点提升搜索结果。

可以使用function score query:

来完成
GET blog/_search
{
  "query": {
    "function_score": {
      "query": {
        "match": {
          "author-title": "developer"
        }
      },
      "functions": [
        {
          "filter": {
            "range": {
              "views": {
                "from": 1
              }
            }
          }, 
          "field_value_factor": {
            "field": "views"
          }
        }
      ]
    }
  }
}

我使用范围过滤器确保当视图数量为0(得分也为0)时field_value_factor不会影响得分。

现在,当我尝试运行此查询时,我将得到以下异常:

nested: ElasticsearchException[Unable to find a field mapper for field [views]]; }]

这是有道理的,因为该字段不存在于索引中的任何位置。 如果我要在索引时添加views = 0,我就不会遇到上述问题,因为该字段在索引中是已知的。但在我的用例中,我无法在索引时或映射上添加此内容。

基于在函数分数查询中使用范围过滤器的能力,我想我可以使用exists filter来确保只有当字段实际存在时才会执行field_value_factor部分索引,但没有这样的运气:

GET blog/_search
{
  "query": {
    "function_score": {
      "query": {
        "match": {
          "author-title": "developer"
        }
      },
      "functions": [
        {
          "filter": {
            "bool": {
              "must": [
                {
                  "exists": {
                    "field": "views"
                  }
                },
                {
                  "range": {
                    "views": {
                      "from": 1
                    }
                  }
                }
              ]
            }
          },
          "field_value_factor": {
            "field": "views"
          }
        }
      ]
    }
  }
}

仍然给出:

nested: ElasticsearchException[Unable to find a field mapper for field [views]]; }]

在解析field_value_factor之前,我希望Elasticsearch首先应用过滤器。

有关如何解决此问题的任何想法,不使用映射文件或在索引时或脚本期间修复?

1 个答案:

答案 0 :(得分:3)

您看到的错误发生在查询解析时,即尚未执行任何操作。那时,FieldValueFactorFunctionParser构建了稍后要执行的filter_value_factor函数,但它注意到映射类型中不存在views字段。

请注意,过滤器尚未执行,就像filter_value_factor函数一样,它仅由FunctionScoreQueryParser解析。

我想知道为什么你不能简单地在你的映射类型中添加一个字段,就像运行它一样简单

curl -XPUT 'http://localhost:9200/blog/_mapping/page' -d '{
    "page" : {
        "properties" : {
            "views" : {"type" : "integer"}
        }
    }
}'

如果这绝对不是一个选项,另一种可能性就是使用script_score代替,如下所示:

{
  "query": {
    "function_score": {
      "query": {
        "match": {
          "author-title": "developer"
        }
      },
      "functions": [
        {
          "filter": {
            "range": {
              "views": {
                "from": 1
              }
            }
          }, 
          "script_score": {
            "script": "_score * doc.views.value"
          }
        }
      ]
    }
  }
}