簡體   English   中英

Nodejs 無法處理 Elasticsearch 長整數

[英]Nodejs cannot handle Elasticsearch long integers

最近,我遇到了一個令人沮喪的問題。

  • 如您所知,在 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
            ]
        }
    ]
}

}

我怎樣才能克服這個問題?

正確的長期解決方案 #1:等待“ JSON.parse source text access ”提案成為現實,然后使用適當的“reviver”function 在適當的地方將原始源解析為 BigInt。


正確的長期解決方案 #2:將 ElasticSearch 格式化為大於 MAX_SAFE_INTEGER 的整數,而不是數字文字(例如字符串),因此您可以使用BigInt(...)構造函數手動解析它們。


短期 hack:在解析 JSON 字符串之前手動將大的 integer 文字轉換為字符串,然后通過在需要的地方創建 BigInts 來修復 object(或者,或者,使用“ 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]);
}

警告:這有點脆弱,很容易想象它不起作用的情況,但對於提供的示例來說,它應該足夠好。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM