Nodejs无法处理Elasticsearch长整数

mzaanser  于 2022-12-03  发布在  ElasticSearch
关注(0)|答案(1)|浏览(142)

最近,我遇到了一个令人沮丧的问题。

  • 如您所知,在Nodejs(javascript)中,您可以可靠地使用最大Number.MAX_SAFE_INTEGER,它是9,007,199,254,740,991,而不会面临精度损失的问题。
  • 我在项目中使用Elasticsearch,“search_after”用于分页。我必须获取最后一次命中的排序值,并将其值作为“search_after”来获取下一个数据。然而,sort的值是[-9223372036854775808,11763]。

但是,9223372036854775808大于Number.MAX_SAFE_INTEGER。因此,我丢失了精度,无法获取下一个结果。
如果您需要示例,Elasticsearch的结果是
`

{
    "took": 117,
    "timed_out": false,
    "_shards": {
        "total": 3,
        "successful": 3,
        "skipped": 0,
        "failed": 0
    },
    "hits": {
        "total": {
            "value": 40,
            "relation": "eq"
        },
        "max_score": 100.0,
        "hits": [
            {
                "_index": "test",
                "_type": "_doc",
                "_id": "11763",
                "_score": 100.0,
                "_source": {
                "data": "dummy"
                },
                "sort": [
                    -9223372036854775808,
                    11763
                ]
            }
        ]
    }
}

`
但是,Nodejs将此响应解析为

{
"took": 117,
"timed_out": false,
"_shards": {
    "total": 3,
    "successful": 3,
    "skipped": 0,
    "failed": 0
},
"hits": {
    "total": {
        "value": 40,
        "relation": "eq"
    },
    "max_score": 100,
    "hits": [
        {
            "_index": "test",
            "_type": "_doc",
            "_id": "11763",
            "_score": 100,
            "_source": {
                "data": "dummy"
            },
            "sort": [
                -9223372036854776000 /*Precisions were lost*/,
                11763
            ]
        }
    ]
}

}
我怎样才能克服这个问题呢?

vvppvyoh

vvppvyoh1#

正确的长期解决方案#1:等待“JSON.parse source text access“提议成为现实,然后在适当的地方使用适当的“reviver”函数将原始源代码解析为BigInt。
正确的长期解决方案2:将ElasticSearch格式大于MAX_SAFE_INTEGER的整数设置为数字文字以外的形式(例如字符串),这样您就可以使用BigInt(...)构造函数手动解析它们。
短期黑客:在解析JSON字符串之前,手动将大整数文字转换为字符串,然后在需要的地方创建BigInts来修复对象(或者,使用“reviver”函数)。

src = src.replaceAll(/(-?\d{15,})/g, '"$1"');
let obj = JSON.parse(src);
for (let h of obj.hits.hits) {
  h.sort[0] = BigInt(h.sort[0]);
}

警告:这有点脆弱,很容易想象它不起作用的情况,但对于提供的示例来说,它应该足够好了。

相关问题