MongooseJS 在填充后返回空数组

Posted

技术标签:

【中文标题】MongooseJS 在填充后返回空数组【英文标题】:MongooseJS returning empty array after population 【发布时间】:2018-06-04 13:19:02 【问题描述】:

我正在编写一个使用 Node.js 和 MongooseJS 作为处理数据库调用的中间件的应用程序。

我的问题是我有一些嵌套模式,其中一个以错误的方式填充。当我跟踪人口的每一步时 - 所有数据都很好,除了 devices 数组,它是空的。我仔细检查了数据库,该数组中有数据,所以应该没问题。

我有 Room 架构。 Room 的每个对象都有一个名为 DeviceGroups 的字段。该字段包含一些信息,其中之一是一个名为Devices 的数组,其中存储了分配给父房间的设备。

正如您在代码中看到的,我正在根据服务器请求中的 ID 找到一个房间。一切都很好,数据与数据库中的数据一致。问题是devices 数组是空的。

这是 MongooseJS 的某种怪癖,还是我在这里做错了什么,devices 数组返回为空?我检查了数据库本身,里面有一些数据,所以数据很好,错误在粘贴代码的某个地方。

代码:

架构:

const roomSchema = Schema(
    name: 
        type: String,
        required: [true, 'Room name not provided']
    ,
    deviceGroups: [
        type: Schema.Types.ObjectId,
        ref: 'DeviceGroup'
    ]
,  collection: 'rooms' );

const deviceGroupSchema = Schema(
    parentRoomId: 
        type: Schema.Types.ObjectId,
        ref: 'Room'
    ,
    groupType: 
        type: String,
        enum: ['LIGHTS', 'BLINDS', 'ALARM_SENSORS', 'WEATHER_SENSORS']
    ,
    devices: [
        
            type: Schema.Types.ObjectId,
            ref: 'LightBulb'
        ,
        
            type: Schema.Types.ObjectId,
            ref: 'Blind'
        
    ]
,  collection: 'deviceGroups' );

const lightBulbSchema = Schema(
    name: String,
    isPoweredOn: Boolean,
    currentColor: Number
,  collection: 'lightBulbs' );

const blindSchema = Schema(
    name: String,
    goingUp: Boolean,
    goingDown: Boolean
,  collection: 'blinds' );

数据库调用:

Room
    .findOne( _id: req.params.roomId )
    .populate(
        path: 'deviceGroups',
        populate: 
            path: 'devices'
        
    )
    .lean()
    .exec(function(err, room) 
        if (err) 
            res.send(err);
         else 
            room.deviceGroups.map(function(currentDeviceGroup, index) 
                if (currentDeviceGroup.groupType === "BLINDS") 
                    var blinds = room.deviceGroups[index].devices.map(function(currentBlind) 
                    return 
                        _id: currentBlind._id,
                        name: currentBlind.name,
                        goingUp: currentBlind.goingUp,
                        goingDown: currentBlind.goingDown
                    
                );
                res.send(blinds);
            
        );
    
)

【问题讨论】:

我不认为您定义devices 的方式是正确的。在一个数组中拥有多个模式引用的一种方法是使用discriminator 看到这个answer @Molda 你能提供一个简单的例子吗?当然,discriminator 正是我要找的,但你链接的另一篇文章有​​点复杂,因为它使用了所有中间件,对我来说不是很清楚。你能想出一个在我的例子中如何使用它的例子吗?谢谢 【参考方案1】:

你能删除你 else 语句中的所有内容吗?

console.log(room)

检查您的 mongo 商店以确保您的集合中有数据。

【讨论】:

我在发布问题之前已经这样做了。正如我在帖子中所写 - 我检查了数据库并保存了正确的 id 引用,我记录了 room 并且所有内容都正确填充,除了 devices 数组为空【参考方案2】:

这是使用discriminator 方法能够在单个数组中使用多个模式的示例。

const roomSchema = Schema(
    name: 
        type: String,
        required: [true, 'Room name not provided']
    ,
    deviceGroups: [ type: Schema.Types.ObjectId, ref: 'DeviceGroup' ]
);

const deviceGroupSchema = Schema(
    parentRoom:  type: Schema.Types.ObjectId, ref: 'Room' ,
    groupType: 
        type: String,
        enum: ['LIGHTS', 'BLINDS', 'ALARM_SENSORS', 'WEATHER_SENSORS']
    ,
    devices: [ type: Schema.Types.ObjectId, ref: 'Device' ]
);

// base schema for all devices
function DeviceSchema() 
  Schema.apply(this, arguments);

  // add common props for all devices 
  this.add(
    name: String
  );


util.inherits(DeviceSchema, Schema);

var deviceSchema = new DeviceSchema();

var lightBulbSchema = new DeviceSchema(
    // add props specific to lightBulbs
    isPoweredOn: Boolean,
    currentColor: Number   
);

var blindSchema = new DeviceSchema(
    // add props specific to blinds
    goingUp: Boolean,
    goingDown: Boolean
);

var Room = mongoose.model("Room", roomSchema );
var DeviceGroup = mongoose.model("DeviceGroup", deviceGroupSchema );

var Device = mongoose.model("Device", deviceSchema );

var LightBulb = Device.discriminator("LightBulb", lightBulbSchema );
var Blind = Device.discriminator("Blind", blindSchema );

// this should return all devices
Device.find()
// this should return all devices that are LightBulbs
LightBulb.find()
// this should return all devices that are Blinds
Blind.find()

在集合中,您将在每个设备上看到 __t 属性 根据使用的模式(灯泡或盲)使用值

我还没有尝试过代码,也有一段时间没有使用猫鼬了,但我希望它能工作:)

更新 - 经过测试的工作示例

var mongoose = require('mongoose');
var Schema = mongoose.Schema;
var util = require('util');

const roomSchema = Schema(
    name: 
        type: String,
        required: [true, 'Room name not provided']
    ,
    deviceGroups: [ type: Schema.Types.ObjectId, ref: 'DeviceGroup' ]
);

const deviceGroupSchema = Schema(
    parentRoomId:  type: Schema.Types.ObjectId, ref: 'Room' ,
    groupType: 
        type: String,
        enum: ['LIGHTS', 'BLINDS', 'ALARM_SENSORS', 'WEATHER_SENSORS']
    ,
    devices: [ type: Schema.Types.ObjectId, ref: 'Device' ]
);

// base schema for all devices
function DeviceSchema() 
  Schema.apply(this, arguments);

  // add common props for all devices 
  this.add(
    name: String
  );


util.inherits(DeviceSchema, Schema);

var deviceSchema = new DeviceSchema();

var lightBulbSchema = new DeviceSchema(
    // add props specific to lightBulbs
    isPoweredOn: Boolean,
    currentColor: Number   
);

var blindSchema = new DeviceSchema();
blindSchema.add(
    // add props specific to blinds
    goingUp: Boolean,
    goingDown: Boolean
);


var Room = mongoose.model("Room", roomSchema );
var DeviceGroup = mongoose.model("DeviceGroup", deviceGroupSchema );

var Device = mongoose.model("Device", deviceSchema );

var LightBulb = Device.discriminator("LightBulb", lightBulbSchema );
var Blind = Device.discriminator("Blind", blindSchema );


var conn = mongoose.connect('mongodb://127.0.0.1/test',  useMongoClient: true );

conn.then(function(db)

    var room = new Room(
        name: 'Kitchen'
    );

    var devgroup = new DeviceGroup(
        parentRoom: room._id,
        groupType: 'LIGHTS'
    );

    var blind = new Blind(
        name: 'blind1',
        goingUp: false,
        goingDown: true
    );
    blind.save();

    var light = new LightBulb(
        name: 'light1',
        isPoweredOn: false,
        currentColor: true
    );
    light.save();

    devgroup.devices.push(blind._id);
    devgroup.devices.push(light._id);
    devgroup.save();

    room.deviceGroups.push(devgroup._id);
    room.save(function(err)
        console.log(err);
    );

    // Room
    // .find()
    // .populate(
    //     path: 'deviceGroups',
    //     populate: 
    //         path: 'devices'
    //     
    // )
    // .then(function(result)
    //     console.log(JSON.stringify(result, null, 4));
    // );

).catch(function(err)

);

【讨论】:

你提议调用函数util.inherits(DeviceSchema, Schema);。我的问题是:util 是什么?我没有看到它在任何地方宣布。它是像 NPM 的另一个包还是像 mongoose 本身的东西? 我使用了您的解决方案,但我仍然得到一个空数组。我检查了数据库,数据保存在那里。这是输出: [ _id: undefined, name: undefined, goingUp: undefined, goingDown: undefined ] util 是内置模块,只需要它var util = require('util') 谢谢!您提供的示例有效!此外,它帮助我更好地理解了discriminatormongoose 本身。我还需要在discriminator 上做一些工作,但是,多亏了你,我离我更近了! 我很高兴能帮上忙。还有一个我想指出的。 Room.find 调用填充设备组和设备将对 db 进行 3 次单独调用,因为它需要查询 3 个集合。如果可能的话,我肯定会尝试通过完全避免设备组来简化它。这只是我的看法,但需要牢记。

以上是关于MongooseJS 在填充后返回空数组的主要内容,如果未能解决你的问题,请参考以下文章

是否可以在 mongoosejs 模式中填充自引用?

mongoosejs 定义复杂模型

使用多个 mongo 查询填充数组 [重复]

使用多个 mongo 查询填充数组 [重复]

Mongoose 填充返回空数组

Mongoose 填充返回空数组