Elasticsearch 对日期字段进行条件排序

Elasticsearch conditional sort on date field

我正在尝试对日期字段 registeredAt 上的 Elastic Search 查询结果进行排序。但是,registeredAt 并不存在于所有 returned 的文档中。在那种情况下,我希望排序在替代字段 invitedAt.

上查找日期

如果我们有 3 个匹配项,如下所示:


    hits = [
    {
       id: 'hit2'
       registeredAt: '2021-06-01T23:00:00.000Z',
       invitedAt: '2021-05-31T23:00:00.000Z'
    },
    {
       id: 'hit3'
       invitedAt: '2021-05-31T23:00:00.000Z'
    },
    {
       id: 'hit1'
       invitedAt: '2021-06-04T23:00:00.000Z'
    },
    
    ],

然后我希望按从最近到最不最近的顺序 return 对它们进行排序:[hit1, hit2, hit3]。 在每个文档中,排序脚本应查找 registeredAt 字段并将该日期作为排序值,如果该字段不存在,则查看 invitedAt 的值并将其作为排序值价值。 从这个意义上说,hit1 没有 registeredAt 并且具有 invitedAt 的最近日期,因此应该排在第一位。 hit2 有一个 registeredAt 字段,该字段的日期比 hit3invitedAt 日期更新(后者没有 registeredAt 字段。

我这样写查询:

client.search({
        index: 'users',
        track_total_hits: true,
        sort: {
        _script: {
          type: 'number',
          script: {
            lang: 'painless',
            source:
              "if (!doc.containsKey('registeredAt') || doc['registeredAt'].empty) { return doc['invitedAt'].value; } else { return doc['registeredAt'].value }",
          },
          order: 'desc',
        },
      },
        body: {
          from: skip,
          size: limit,
          query: {...},
        },
      })
      

查询运行没有错误,但排序不起作用,文档按索引的顺序return编辑。

我假设 registeredAtinvitedAt 在映射中是 date。 此查询应该有效。我添加的是获取值后调用.getMillis()

{
  "sort": [
    {
      "_script": {
        "type": "number",
        "script": {
          "lang": "painless",
          "source": """
            if (!doc.containsKey('registeredAt') || doc['registeredAt'].empty) { 
              return doc['invitedAt'].value.getMillis();
              
            } 
            else { 
              return doc['registeredAt'].value.getMillis();
            }
          """
        },
        "order": "desc"
      }
    }
  ]
}

编辑:.getMillis() 在版本 7.x 中被删除。 .toInstant().toEpochMilli() 应该改用。

这是查询:

{
  "sort": [
    {
      "_script": {
        "type": "number",
        "script": {
          "lang": "painless",
          "source": """
            if (!doc.containsKey('registeredAt') || doc['registeredAt'].empty) { 
              return doc['invitedAt'].value.toInstant().toEpochMilli();
              
            } 
            else { 
              return doc['registeredAt'].value.toInstant().toEpochMilli();
            }
          """
        },
        "order": "desc"
      }
    }
  ]
}