【问题标题】:Is it possible to boost 'newest' items using elasticsearch? (FOQElasticaBundle)是否可以使用弹性搜索来提升“最新”项目? (FOQElasticaBundle)
【发布时间】:2012-08-18 22:52:49
【问题描述】:

我目前正在通过FOQElasticaBundle 在我的 Symfony2 应用程序中实现弹性搜索,到目前为止,基于应用于我的“故事”实体的各个领域的提升,它一直运行良好。这是配置:

foq_elastica:
    clients:
        default: { host: localhost, port: 9200 }

    indexes:
        website:
            client: default
            types:
                story:
                    mappings:
                        title: { boost: 8 }
                        summary: { boost: 5 }
                        text: { boost: 3 }
                        author:
                    persistence:
                        driver: orm # orm, mongodb, propel are available
                        model: Acme\Bundle\StoryBundle\Entity\Story
                        provider:
                            query_builder_method: createIsActiveQueryBuilder
                        listener:
                            service: acme_story.search_index_listener
                        finder:

但是,我还想根据故事的“published_at”日期应用提升,以便昨天发布的故事会在 6 个月前发布的故事之前出现在结果中 - 即使较旧的故事有稍微好一点的分数(显然这需要一些调整)。这可能吗?

如果有人可以让我知道如何使用 FOQElasticaBundle 来实现这一点,那就太好了,但如果你能让我知道如何直接在 elasticsearch 中实现这一点,我将不胜感激,这样我就可以自己尝试实现该行为,并且如果需要,请为捆绑包做出贡献。

谢谢。

【问题讨论】:

  • 你为什么不修改你的查询,以便你 orderBy published_at?
  • @Patt 谢谢,但您指的是哪个查询?我刚刚订购了 query_builder_method 的结果,但这没有任何效果。然后我尝试将发送到 elasticsearch 的查询更改为以下内容: { "query" : { "query_string" : { "query" : "something" } }, "sort" : [ { "publishedAt" : "desc" } ] }。这导致了错误:“解析失败 [未找到 [publishedAt] 的映射以便排序”。在我的映射配置下添加“publishedAt:”没有帮助。
  • 好的,忽略我之前的评论...在将“publishedAt”映射添加到我的配置并运行“app/console foq:elastica:populate”以应用更改后,我能够进行排序到弹性搜索。然而,这并不是我真正想要的 - 这意味着与搜索词的非常部分匹配将出现在可能仅在几秒钟前发布的完全匹配之前。我绝对认为需要根据故事的“新近度”进行某种提升,但这似乎在所有文档中都没有......

标签: php symfony elasticsearch


【解决方案1】:

哇,经过大量的实验和数小时的 Internet 拖网,我终于设法获得了所需的行为! (全部归功于Clinton Gormley。)

映射配置:

mappings:
    title: { boost: 8 }
    summary: { boost: 5 }
    text: { boost: 3 }
    author:
    publishedAt: { type: date }

这是使用 PHP 客户端 Elastica 动态构建查询以使用原始映射和发布日期进行提升的代码:

$query = new \Elastica_Query_Bool();
$query->addMust(new \Elastica_Query_QueryString($queryString));

$ranges = array();
for ($i = 1; $i <= 5; $i++) {
    $date = new \DateTime("-$i month");

    $currentRange = new \Elastica_Query_Range();
    $currentRange->addField('publishedAt', array(
        'boost' => (6 - $i),
        'gte' => $date->getTimestamp()
    ));

    $ranges[] = $currentRange->toArray();
}

$query->addShould($ranges);

/** @var $pagerfanta Pagerfanta */
$pagerfanta = $this->getFinder()->findPaginated($query);

对于那些对原始 elasticsearch 查询更感兴趣的人(为简洁起见,仅提供 3 个日期范围)...

curl -XPOST 'http://localhost:9200/website/story/_search?pretty=true' -d '
{
  "query" : {
    "bool" : {
      "must" : {
        query_string: {
          query: "<search term(s)>"
        }
      },
      "should" : [
        {
          "range" : {
            "publishedAt" : {
              "boost" : 5,
              "gte" : "<1 month ago>"
            }
          }
        },
        {
          "range" : {
            "publishedAt" : {
              "boost" : 4,
              "gte" : "<2 months ago>"
            }
          }
        },
        {
          "range" : {
            "publishedAt" : {
              "boost" : 3,
              "gte" : "<3 months ago>"
            }
          }
        }
      ]
    }
  }
}'

【讨论】:

  • 干得好@RobMasters。这是完美的!我希望我没有误导你太多......你带来的解决方案真的很可靠!
  • 子问题:为什么要使用 "gte" 而不是 "from"-"to" 日期范围?
  • @g.annunziata - 原因是提升应该是累积的,以便正确确定最近项目的优先级。即 6 周前添加的内容会因大于或等于 和 的日期而获得提升,而 10 周前添加的内容只会获得 gte 提升。这只是对我有用的一个例子——你可以通过调整提升标准来获得更好的结果。
  • 性能怎么样?恐怕这会将评分应用于您的所有文件?
【解决方案2】:

您可以使用衰减评分函数来降低评分与时间的关系:

{
 "query": {
 "function_score": {
    "functions": [
     {
      "linear": {
        "pubdate": {
          "origin": 1398673886,
          "scale": "1h",
          "offset": 0,
          "decay": 0.1
        }
      }
    }
    ]
   }
  }
 }

【讨论】:

  • PHP中如何设置?
【解决方案3】:

基于 function_score 的完整 elasticsearch 5 示例。请参阅this blogpostfunction_score docs 了解更多信息。

允许在没有“硬截止”的高斯曲线上基于多个日期范围、具有不同强度的近期条目提升。

{
    "query": {
        "function_score": {

            "score_mode": "sum", // All functions outputs get summed
            "boost_mode": "multiply", // The documents relevance is multiplied with the sum

            "functions": [
                {
                    // The relevancy of old posts is multiplied by at least one.
                    // Remove if you want to exclude old posts
                    "weight": 1
                },
                {
                    // Published this month get a big boost
                    "weight": 5,
                    "gauss": {
                        "date": { // <- Change to your date field name
                            "origin": "2017-04-07", // Change to current date
                            "scale": "31d",
                            "decay": 0.5
                        }
                    }
                },
                {
                    // Published this year get a boost
                    "weight": 2,
                    "gauss": {
                        "date": { // <- Change to your date field name
                            "origin": "2017-04-07", // Change to current date
                            "scale": "356d",
                            "decay": 0.5
                        }
                    }
                }
            ],

            "query": {
                // The rest of your search here, change to something relevant
                "match": { "title": "< your search string >" }
            }
        }
    }
}

【讨论】:

  • 博文链接看起来也引用了函数分数文档,您还记得那是哪篇博文吗?
  • @autopoietic 对不起,不记得了。
猜你喜欢
  • 1970-01-01
  • 2012-12-30
  • 2022-07-29
  • 2017-07-22
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2020-09-05
相关资源
最近更新 更多