Node.js处理Elasticsearch长整数丢失精度问题求助
解决Node.js解析Elasticsearch超大整数精度丢失问题
给你几个可行的解决思路:
1. 让Elasticsearch返回字符串格式的整数
直接从源头解决,修改查询或者字段映射,把导致精度丢失的超大整数以字符串形式返回。比如在查询时用脚本把数值转成字符串作为排序字段:
{ "query": { "match_all": {} }, "sort": [ { "_script": { "type": "string", "script": { "source": "doc['your_large_int_field'].value.toString()" }, "order": "asc" } }, "_id" ] }
这样返回的sort数组里第一个元素就是字符串,Node.js解析时不会丢精度,后续给search_after传参时直接用这个字符串就行,Elasticsearch能正确识别。
2. 在Node.js里用BigInt处理
如果没法改Elasticsearch的返回逻辑,就在解析JSON的时候把超大整数转成BigInt,避免精度丢失。用JSON.parse的reviver参数来做:
// 假设elasticRawResponse是Elasticsearch返回的原始JSON字符串 const parsedResponse = JSON.parse(elasticRawResponse, (key, value) => { if (typeof value === 'number' && !Number.isSafeInteger(value)) { return BigInt(value.toString()); } return value; }); // 取最后一条数据的sort值,传给search_after时转成字符串 const lastHit = parsedResponse.hits.hits.at(-1); const searchAfter = lastHit.sort.map(item => typeof item === 'bigint' ? item.toString() : item );
3. 配置Elasticsearch客户端自动处理
如果用的是官方@elastic/elasticsearch客户端,可以自定义序列化器,让它自动把超大整数转成BigInt:
const { Client, Serializer } = require('@elastic/elasticsearch'); class BigIntSerializer extends Serializer { deserialize(buffer) { return JSON.parse(buffer.toString(), (key, value) => { if (typeof value === 'number' && !Number.isSafeInteger(value)) { return BigInt(value.toString()); } return value; }); } } const client = new Client({ node: 'http://your-es-host:9200', serializer: new BigIntSerializer() });
之后客户端返回的数据里,超大整数都会是BigInt类型,用的时候转成字符串传给search_after就没问题了。
优先推荐第一种方法,从源头避免精度问题;如果改不了ES的配置或查询,再考虑后面两种Node端的处理方式。
内容的提问来源于stack exchange,提问作者Fatih Kurnaz
相关产品推荐
相关产品推荐

