2016-06-28 1 views
0

私は2つのスキーマを持っています:デバイスとマップ。なぜ私の配列はMongooseを使用して設定されていません

デバイス:あなたが見ることができるように

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'}] 
}); 

、私の地図には、デバイスを参照し、私のデバイスがマップを参照するmapIdフィールドを持つ配列を持っています。さて、私は.populate()を呼び出そうとしていますので、マップをそのデバイスの配列とともに取得できます。私はやっている:

module.exports.getMapByIdAndPopulate = function(mapId, callback){ 
    Map.findOne({_id: mapId}).populate('devices').exec(callback); 
}; 

これはマップを返すが、そうでなければデバイス配列は空である。また、私のDBに次のようにデバイスを作成します:

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] 
    }); 

デバイスの配列でマップを取得するにはどうすればよいですか?また、わかりやすいデータが正しく入力されているかどうかはわかりませんが、マップ配列にデバイスを挿入することはありません。

答えて

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はデバイスのオブジェクト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 } 

データベースレコードは、データが期待どおりであることを示します.DeviceはMapのObjectIdを格納し、MapはDeviceのObjectIDを「devices」パスの配列に格納しました。

これは、レコードが正しく読み込まれていることを示しています。これは、スキーマとクエリが正しいことを意味しています。

したがって、人口があなたの側でうまくいかない理由を調べる必要があります。

データベース内のデータを最初に確認し、mapsコレクションの "devices"配列に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) 
} 
+0

感謝!!!問題は、私はマップを作成し、デバイスは後で作成されます。これどうやってするの?たとえば、マップの作成直後にデバイスを作成しているとします。別の時間にデバイスをマップ配列に配置するにはどうすればよいですか? – unconditionalcoder

+0

デバイスの作成が完了したら、** 1)** 'Map.findById(mapId、" devices ")'、新しいデバイスを 'devices'配列に追加し、' .save() 'を更新する地図;または** 2)** Map.update({_ id:mapId}、{$ addToSet:{"devices":device._id}}) '' – kazenorin

0

まず、この構文を使用するときに、あなたがそれを行うと確信していることを確認してください。

var device = new Device({}); 

オブジェクトを作成しているだけなので、まだオブジェクトをmongoに保存していません。そのためには、ちょうど

var device = new Device({}); 
device.save(function(err){ 
    //if err, wrong query 
    //else, everything went ok 
}); 

.SAVEが非同期であることに注意してください。

一方、あなたが言ったように、マップコレクションの下のデバイス配列には、デバイスのid参照を挿入しませんでした。私はあなたが人口方法を誤解していると思います。 populateメソッドは、指定された配列(この場合)に含まれるすべてのIDを検索し、モデル内の参照されたコレクションを使用して各要素を設定します。だから、あなたがその配列に何も持っていなければ、モンゴルには何もありません。マップオブジェクトにデバイスを手動で挿入する必要があります。

関連する問題