You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在ElasticSearch中实现条件排序,让有效期内的推广课程优先展示

实现方案

方案1:多字段优先级排序(最直观,易调试)

核心逻辑是新增一个自定义排序因子,将符合推广条件的课程标记为更高排序优先级,排在所有普通课程之前,之后再执行你原来的普通排序规则。

ES原生DSL示例:

{
  "query": {
    // 这里放你原来的搜索条件,比如关键词匹配、分类筛选等
    "match_all": {}
  },
  "sort": [
    // 第一排序规则:符合推广条件的优先
    {
      "_script": {
        "type": "number",
        "script": {
          "lang": "painless",
          "source": """
            // 判断是否为有效推广课程
            if (doc['is_sponsored'].value == 1 
                && doc['sponsored_start_date'].value.toInstant().isBeforeZonedDateTime(new ZonedDateTime()) 
                && doc['sponsored_end_date'].value.toInstant().isAfterZonedDateTime(new ZonedDateTime())) {
              return 2;
            }
            return 1;
          """
        },
        "order": "desc"
      }
    },
    // 第二排序规则:你原来的普通排序,比如按相关度、发布时间、销量等,示例是按相关度得分倒序
    {
      "_score": {
        "order": "desc"
      }
    }
  ]
}

如果存在ES和PHP时区不一致的问题,也可以直接在PHP侧生成当前时间传入脚本,替换掉new ZonedDateTime()即可:

"params": {
  "now": "<?php echo date('Y-m-d H:i:s');?>"
}

方案2:function_score加权(适合默认按相关度排序的场景)

给有效推广课程加上一个足够大的权重值,确保它的整体得分远高于普通课程,自动排在最前方。

ES原生DSL示例:

{
  "query": {
    "function_score": {
      "query": {
        // 这里放你原来的搜索条件
        "match_all": {}
      },
      "functions": [
        {
          "filter": {
            "bool": {
              "must": [
                {"term": {"is_sponsored": 1}},
                {"range": {"sponsored_start_date": {"lte": "now"}}},
                {"range": {"sponsored_end_date": {"gte": "now"}}}
              ]
            }
          },
          "weight": 10000
        }
      ],
      "boost_mode": "sum"
    }
  }
}

PHP 客户端代码示例(以elasticsearch官方SDK为例)

以下是方案1的PHP实现代码:

<?php
require 'vendor/autoload.php';

$client = Elasticsearch\ClientBuilder::create()->setHosts(['127.0.0.1:9200'])->build();

$params = [
    'index' => 'test',
    'type' => 'courses',
    'body' => [
        'query' => [
            // 替换为你实际的搜索条件
            'match_all' => new stdClass()
        ],
        'sort' => [
            [
                '_script' => [
                    'type' => 'number',
                    'script' => [
                        'lang' => 'painless',
                        'source' => "if (doc['is_sponsored'].value == 1 && doc['sponsored_start_date'].value.toInstant().isBeforeZonedDateTime(new ZonedDateTime()) && doc['sponsored_end_date'].value.toInstant().isAfterZonedDateTime(new ZonedDateTime())) { return 2; } return 1;"
                    ],
                    'order' => 'desc'
                ]
            ],
            [
                '_score' => ['order' => 'desc']
            ]
        ]
    ]
];

$response = $client->search($params);
print_r($response);
?>

注意事项

  • 如果需要调整推广课程内部的排序规则,比如推广结束时间越近越靠前/越晚越靠前,只需要修改script的返回值即可,比如将符合条件的返回值调整为2 + (doc['sponsored_end_date'].value.toInstant().toEpochMilli()/100000000000)即可实现推广过期时间越晚,排序越靠前。
  • 如果字段存在空值,可在script判断中增加doc['字段名'].size() > 0的校验,避免查询报错。
  • 若时区存在差异,推荐在PHP侧生成格式化后的当前时间作为参数传入查询脚本,避免时区不匹配导致的时间判断错误。

内容的提问来源于stack exchange,提问作者Dksingh

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.10.02 04:57:03