gpt4 book ai didi

javascript - 如何在 $geoNear 之后填充子文档

转载 作者:可可西里 更新时间:2023-11-01 10:04:18 24 4
gpt4 key购买 nike

我正在使用 NodeJs 和 Mongoose 并构建一个功能来列出附近的交易。

   Deal.db.db.command({
"geoNear": Deal.collection.name,
"near": [23,67],
"spherical": true,
"distanceField": "dis"
}, function (err, documents) {
if (err) {
return next(err);
}
console.log(documents);
});

交易模式:

var dealSchema = new mongoose.Schema({
title: String,
merchant: {
type: mongoose.Schema.Types.ObjectId,
ref: Merchant,
index: true
}
});

在这里,我获得了所有交易及其与当前位置的距离。在 Deal 模式中,我有一个商家作为引用对象。

如何用每个返回的交易对象填充商家?我是否需要遍历所有返回的 Deal 对象并手动填充?

最佳答案

这实际上有点有趣。当然,您真正不想做的是“深入” native 驱动程序部分,尽管您可能可以使用解决方案 2。这导致有几种方法可以解决这个问题,而无需实际滚动您自己的查询来手动匹配它.

首先进行一些设置。我没有复制您的数据集,而是选择了我之前测试中的一些东西。原理是一样的,所以基本设置:

var mongoose = require('mongoose'),
async = require('async'),
Schema = mongoose.Schema;

mongoose.connect('mongodb://localhost');

var infoSchema = new Schema({
"description": String
});

var shapeSchema = new Schema({
"_id": String,
"amenity": String,
"shape": {
"type": { "type": String },
"coordinates": []
},
"info": { "type": Schema.Types.ObjectId, "ref": "Info" }
});

var Shape = mongoose.model( "Shape", shapeSchema );
var Info = mongoose.model( "Info", infoSchema );

本质上,一个模型带有“地理”信息,另一个模型仅引用我们想要填充的一些信息。还有我对数据的懒惰更改:

{ 
"_id" : "P1",
"amenity" : "restaurant",
"shape" : { "type" : "Point", "coordinates" : [ 2, 2 ] }
}
{
"_id" : "P3",
"amenity" : "police",
"shape" : { "type" : "Point", "coordinates" : [ 4, 2 ] }
}
{
"_id" : "P4",
"amenity" : "police",
"shape" : { "type" : "Point", "coordinates" : [ 4, 4 ] }
}
{
"_id" : "P2",
"amenity" : "restaurant",
"shape" : { "type" : "Point", "coordinates" : [ 2, 4 ] },
"info" : ObjectId("539b90543249ff8d18e863fb")
}

所以我们可以期望填充其中的一件事。事实证明,$near 查询非常简单,正如预期的那样:

var query = Shape.find(
{
"shape": {
"$near": {
"$geometry": {
"type": "Point",
"coordinates": [ 2, 4 ]
}
}
}
}
);

query.populate("info").exec(function(err,shapes) {
if (err) throw err;
console.log( shapes );
});

这只是调用了 $near 运算符的标准 .find()。这是 MongoDB 2.6 语法,就是这样。但结果正确排序并按预期填充:

[ 
{ _id: 'P2',
amenity: 'restaurant',
info:
{ _id: 539b90543249ff8d18e863fb,
description: 'Jamies Restaurant',
__v: 0 },
shape: { type: 'Point', coordinates: [ 2, 4 ] } },
{ _id: 'P4',
amenity: 'police',
info: null,
shape: { type: 'Point', coordinates: [ 4, 4 ] } },
{ _id: 'P1',
amenity: 'restaurant',
info: null,
shape: { type: 'Point', coordinates: [ 2, 2 ] } },
{ _id: 'P3',
amenity: 'police',
info: null,
shape: { type: 'Point', coordinates: [ 4, 2 ] } }
]

这非常好,而且是一种简单的调用方式。收获?遗憾的是,将运算符更改为 $geoNear 以考虑球面几何开始引发错误。因此,如果您想要那样,就不能像以前那样做事。

另一种方法是 Mongoose 有一个 .geoNear()支持的功能。但就像 db.command 调用一样,它不会返回 Mongoose 文档或其他接受 .populate() 的模型类型对象。解决方案?稍微玩一下输出:

var query = Shape.geoNear({
"type": "Point",
"coordinates": [ 2, 4 ]
},{spherical: true},function(err,shapes) {
if (err) throw err;

shapes = shapes.map(function(x) {
delete x.dis;
var a = new Shape( x.obj );

return a;
});
Shape.populate( shapes, { path: "info" }, function(err,docs) {
if (err) throw err;

console.log( docs );

});

所以这里返回的结果是一个原始对象数组。但是通过一些操作,您可以将它们变成可以与 .populate() 一起使用的东西。也可以从模型类中调用的方法,如图所示。

结果当然是一样的,尽管字段顺序可能有点不同。而且您不需要自己迭代调用查询。这就是 .populate() 实际上所做的所有事情,但我认为我们可以同意使用 .populate() 方法至少看起来更干净而且不会为此重新发明轮子。

关于javascript - 如何在 $geoNear 之后填充子文档,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/24197235/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com