NodeJS+MongoDB使用Promise提取文档经纬度并转换为指定数组问题
如何用Node.js + MongoDB Promise方式提取指定字段并转换为目标数组格式?
问题描述:
我想用NodeJS结合MongoDB,通过Promise方式从所有匹配name: "Mark"的文档中提取latitude和longitude字段,转换为如下格式的数组:
[{ lat: -31.563910, lng: 147.154312 }, ...]
当前编写的Promise代码返回了所有字段(如name、gender等),尝试通过Presults.latitude或Presults[0].latitude获取值时均得到undefined,但用回调方式可以正常运行。
我的Promise代码:
const promises = [ dbo.collection("users").find({ name: "Mark" }, { latitude: 1, longitude: 1, _id: 0 }).toArray() ] Promise.all(promises).then(function (Presults) { console.log(Presults); }).catch(function (err) { console.log(err); });
正常运行的回调代码:
dbo.collection("users").find( { name: "Mark" }, { latitude: 1, longitude: 1, _id: 0 }).toArray(function (err, result) { if (err) throw err; var array1 = []; var z = { "lat": result[0].latitude, "lng": result[0].longitude }; var y = { "lat": result[0].latitude, "lng": result[0].longitude }; array1.push(z, y); console.log(array1); });
问题分析与解决方案:
1. 投影参数格式错误(核心问题)
在新版MongoDB Node.js驱动中,find方法的第二个参数是选项对象,投影需要明确放在projection字段里。你直接传{ latitude: 1, longitude: 1, _id: 0 }会被驱动忽略,导致返回所有字段,这就是为什么你拿不到latitude和longitude的原因。
2. Promise.all的冗余使用与结果处理
你只传入了一个Promise到Promise.all,所以它返回的结果是一个包含查询结果数组的数组(即Presults是[文档数组])。直接访问Presults[0].latitude当然会undefined,因为Presults[0]是整个文档数组,数组本身没有latitude属性,你需要遍历数组里的每个文档。
修正后的代码:
方式一:直接使用单个Promise(更简洁)
dbo.collection("users") // 正确指定投影参数 .find({ name: "Mark" }, { projection: { latitude: 1, longitude: 1, _id: 0 } }) .toArray() .then(function(documents) { // 遍历文档,转换为目标格式 const formattedLocations = documents.map(doc => ({ lat: doc.latitude, lng: doc.longitude })); console.log(formattedLocations); }) .catch(function(err) { console.error("查询出错:", err); });
方式二:如果确实需要用Promise.all(比如多个并行查询)
const userQuery = dbo.collection("users") .find({ name: "Mark" }, { projection: { latitude: 1, longitude: 1, _id: 0 } }) .toArray(); Promise.all([userQuery]) // 解构数组拿到实际的文档列表 .then(function([documents]) { const formattedLocations = documents.map(doc => ({ lat: doc.latitude, lng: doc.longitude })); console.log(formattedLocations); }) .catch(err => console.error("查询出错:", err));
关键说明:
- 用
projection字段明确指定要返回的字段,确保驱动正确解析你的需求。 - 使用
Array.map()遍历所有匹配的文档,批量转换格式,而不是像回调示例里只处理第一个文档重复添加。 - 如果只执行单个查询,完全不需要
Promise.all,直接使用find().toArray()返回的Promise即可,代码更简洁。
内容的提问来源于stack exchange,提问作者Andrei Charnyshou
相关产品推荐
相关产品推荐

