我有两个架构:设备和地图。
设备:
var DeviceSchema = mongoose.Schema({
deviceName:{
type: String,
required: true,
index: true
},
roomCapacity: {
type: Number
},
roomImagePath:{
type: String,
},
mapId:{
type: Schema.Types.ObjectId,
ref: 'Map',
required: true
},
coords:{
type: [Number], //[xcoord, ycoord]
required: true
},
createdAt: { type: Date, default: Date.now }
});
地图
var MapSchema = mongoose.Schema({
ownerId:{
type: Schema.Types.ObjectId,
ref: 'User',
required: true
},
mapName: {
type: String
},
mapImagePath:{
type: String,
required: true
},
createdAt: { type: Date, default: Date.now },
devices: [{type: Schema.Types.ObjectId, ref: 'Device'}]
});
如您所见,我的Map有一个引用设备的数组,而我的Device有一个引用地图的mapId字段。现在,我正在尝试调用.populate(),以便我可以检索地图及其数组设备。我在做:
module.exports.getMapByIdAndPopulate = function(mapId, callback){
Map.findOne({_id: mapId}).populate('devices').exec(callback);
};
这会返回地图,但设备数组不应该是空的。另外,我在我的数据库中创建设备如下:
var device = new Device({ //create the device
deviceName: req.body.deviceName,
roomCapacity: req.body.roomCapacity,
roomImagePath: roomImagePath,
mapId: req.body.mapId,
coords: [req.body.xcoord, req.body.ycoord]
});
如何使用其设备阵列检索地图?另外,我不知道我是否理解填充正确,但我从不在Map数组中插入任何设备。
答案 0 :(得分:2)
我已经创建了一个简单的脚本来运行你的模式和查询:
var mongoose = require('mongoose');
var Schema = mongoose.Schema;
var ObjectId = mongoose.Types.ObjectId;
mongoose.connect("mongodb://localhost/mytestdb");
var db = mongoose.connection;
db.on('error', console.error.bind(console, 'connection error:'));
db.once('open', function () {
// Schemas copied from your code, condensed to reduce clutter
var DeviceSchema = mongoose.Schema({
deviceName: {type: String, required: true, index: true},
roomCapacity: {type: Number},
roomImagePath: {type: String},
mapId: {type: Schema.Types.ObjectId, ref: 'Map', required: true},
coords: {type: [Number], required: true},
createdAt: {type: Date, default: Date.now}
});
// Omitted ownerId for simplicity sake
var MapSchema = mongoose.Schema({
mapName: {type: String},
mapImagePath: {type: String, required: true},
createdAt: {type: Date, default: Date.now},
devices: [{type: Schema.Types.ObjectId, ref: 'Device'}]
});
var Device = mongoose.model('Device', DeviceSchema);
var Map = mongoose.model('Map', MapSchema);
// Add Map
new Map({
mapName: "Map 1",
mapImagePath: "mapImagePath 1",
createdAt: new Date(),
devices: []
}).save().then(function (map1) {
// Add a Device
return new Device({
deviceName: "Device 1",
roomCapacity: 123,
roomImagePath: "roomImagePath",
mapId: map1._id,
coords: [345, 456]
}).save().then(function (device1) {
// Add the new Device back to the map
map1.devices.push(device1); // Push the whole device, not just the _id, mongoose would handle this for us
return map1.save();
})
}).then(function (saveResult) {
console.log(saveResult);
// mapId is now an ObjectId
var mapId = saveResult._id;
return Map.findOne({_id: mapId}).populate('devices').exec().then(function (foundMap) {
console.log(foundMap);
});
}).catch(function (err) {
console.error(err);
});
});
控制台输出:
首先,console.log包含新保存的Map,其中包含Device的对象ID:
{ __v: 1,
mapName: 'Map 1',
mapImagePath: 'mapImagePath 1',
_id: 5771e0e5739d78441cff5424,
devices: [ 5771e0e5739d78441cff5425 ],
createdAt: Tue Jun 28 2016 02:28:53 GMT+0000 }
第二个console.log是已填充的.findOne()
:
{ _id: 5771e0e5739d78441cff5424,
mapName: 'Map 1',
mapImagePath: 'mapImagePath 1',
__v: 1,
devices:
[ { _id: 5771e0e5739d78441cff5425,
deviceName: 'Device 1',
roomCapacity: 123,
roomImagePath: 'roomImagePath',
mapId: 5771e0e5739d78441cff5424,
__v: 0,
createdAt: Tue Jun 28 2016 02:28:53 GMT+0000,
coords: [Object] } ],
createdAt: Tue Jun 28 2016 02:28:53 GMT+0000 }
数据库记录显示数据符合预期 - 设备存储了Map的ObjectId,Map将设备的ObjectID存储在"设备"的数组中。路径。
这表明记录已正确填充,这意味着您的架构和查询应该是正确的。
因此,我们应该找出为什么人口并不适合你。
我建议您先检查数据库中的数据,验证"设备" maps
集合的数组包含ObjectId但不包含字符串。还要确保正确命名和映射集合(如果不使用默认名称)
以下是我的数据库的测试数据:
maps
收藏:
{
"_id" : ObjectId("5771e0e5739d78441cff5424"),
"mapName" : "Map 1",
"mapImagePath" : "mapImagePath 1",
"devices" : [
ObjectId("5771e0e5739d78441cff5425")
],
"createdAt" : ISODate("2016-06-28T02:28:53.091+0000"),
"__v" : NumberInt(1)
}
devices
收藏:
{
"_id" : ObjectId("5771e0e5739d78441cff5425"),
"deviceName" : "Device 1",
"roomCapacity" : NumberInt(123),
"roomImagePath" : "roomImagePath",
"mapId" : ObjectId("5771e0e5739d78441cff5424"),
"createdAt" : ISODate("2016-06-28T02:28:53.181+0000"),
"coords" : [
NumberInt(345),
NumberInt(456)
],
"__v" : NumberInt(0)
}
答案 1 :(得分:0)
首先,只是为了确保你按照预期的方式进行,当你使用这种语法时
var device = new Device({});
您只是在创建一个对象,所以还没有将它保存到mongo中。为此,只需
var device = new Device({});
device.save(function(err){
//if err, wrong query
//else, everything went ok
});
请记住 .save 是异步的。
另一方面,正如您所说,您没有将任何设备的id引用插入到map集合下的devices数组中。我认为你误解了populate方法。 populate方法将查看指定数组中包含的所有id(在本例中),并使用模型中引用的集合填充每个元素。所以,如果你在那个数组中没有任何东西,mongo就没有任何东西可以填充。您必须手动将设备插入地图对象。