MongoDB
 sql >> база данни >  >> NoSQL >> MongoDB

Множество препратки към схеми в един масив от схеми - mongoose

Това, което търсите тук, е mongoose .discriminator() метод. Това основно ви позволява да съхранявате обекти от различни типове в една и съща колекция, но да ги имате като различими първокласни обекти.

Имайте предвид, че принципът на "същата колекция" тук е важен за това как .populate() произведения и дефиницията на препратката в съдържащия модел. Тъй като наистина можете да посочите само „един“ модел за справка така или иначе, но има някаква друга магия, която може да накара един модел да се появи толкова много.

Примерен списък:

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

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

//mongoose.set("debug",true);

var scenarioSchema = new Schema({
  "name": String,
  "guns": [{ "type": Schema.Types.ObjectId, "ref": "Gun" }]
});

function BaseSchema() {
  Schema.apply(this, arguments);

  // Common Gun stuff
  this.add({
    "createdAt": { "type": Date, "default": Date.now }
  });
}

util.inherits(BaseSchema, Schema);

var gunSchema = new BaseSchema();

var ak47Schema = new BaseSchema({
  // Ak74 stuff
});

ak47Schema.methods.shoot = function() {
  return "Crack!Crack";
};

var m16Schema = new BaseSchema({
  // M16 Stuff
});

m16Schema.methods.shoot = function() {
  return "Blam!!"
};


var Scenario = mongoose.model("Scenario", scenarioSchema);

var Gun = mongoose.model("Gun", gunSchema );
var Ak47 = Gun.discriminator("Ak47", ak47Schema );
var M16 = Gun.discriminator("M16", m16Schema );


async.series(
  [
    // Cleanup
    function(callback) {
      async.each([Scenario,Gun],function(model,callback) {
        model.remove({},callback);
      },callback);
    },

    // Add some guns and add to scenario
    function(callback) {
      async.waterfall(
        [
          function(callback) {
            async.map([Ak47,M16],function(gun,callback) {
              gun.create({},callback);
            },callback);
          },
          function(guns,callback) {
            Scenario.create({
              "name": "Test",
              "guns": guns
            },callback);
          }
        ],
        callback
      );
    },

    // Get populated scenario
    function(callback) {
      Scenario.findOne().populate("guns").exec(function(err,data) {

        console.log("Populated:\n%s",JSON.stringify(data,undefined,2));

        // Shoot each gun for fun!
        data.guns.forEach(function(gun) {
          console.log("%s says %s",gun.__t,gun.shoot());
        });

        callback(err);
      });
    },

    // Show the Guns collection
    function(callback) {
      Gun.find().exec(function(err,guns) {
        console.log("Guns:\n%s", JSON.stringify(guns,undefined,2));
        callback(err);
      });
    },

    // Show magic filtering
    function(callback) {
      Ak47.find().exec(function(err,ak47) {
        console.log("Magic!:\n%s", JSON.stringify(ak47,undefined,2));
        callback(err);
      });
    }
  ],
  function(err) {
    if (err) throw err;
    mongoose.disconnect();
  }
);

И извеждане

Populated:
{
  "_id": "56c508069d16fab84ead921d",
  "name": "Test",
  "__v": 0,
  "guns": [
    {
      "_id": "56c508069d16fab84ead921b",
      "__v": 0,
      "__t": "Ak47",
      "createdAt": "2016-02-17T23:53:42.853Z"
    },
    {
      "_id": "56c508069d16fab84ead921c",
      "__v": 0,
      "__t": "M16",
      "createdAt": "2016-02-17T23:53:42.862Z"
    }
  ]
}
Ak47 says Crack!Crack
M16 says Blam!!
Guns:
[
  {
    "_id": "56c508069d16fab84ead921b",
    "__v": 0,
    "__t": "Ak47",
    "createdAt": "2016-02-17T23:53:42.853Z"
  },
  {
    "_id": "56c508069d16fab84ead921c",
    "__v": 0,
    "__t": "M16",
    "createdAt": "2016-02-17T23:53:42.862Z"
  }
]
Magic!:
[
  {
    "_id": "56c508069d16fab84ead921b",
    "__v": 0,
    "__t": "Ak47",
    "createdAt": "2016-02-17T23:53:42.853Z"
  }
]

Можете също да декомментирате mongoose.set("debug",true) ред в списъка, за да видите как mongoose всъщност конструира обажданията.

Това показва, че можете да прилагате различни схеми към различни първокласни обекти и дори с различни методи, прикрепени към тях, точно като реални обекти. Mongoose съхранява всичко това в колекция "оръжия" с прикачения модел и ще съдържа всички "типове", посочени от дискриминатора:

var Gun = mongoose.model("Gun", gunSchema );
var Ak47 = Gun.discriminator("Ak47", ak47Schema );
var M16 = Gun.discriminator("M16", m16Schema );

Но също така всеки различен "тип" е рефериран със собствен модел по специален начин. Така че виждате, че когато mongoose съхранява и чете обекта, има специален __t поле, което му казва кой „модел“ да приложи, а оттам и прикачена схема.

Като един пример ние наричаме .shoot() метод, който е дефиниран по различен начин за всеки модел/схема. Освен това можете да използвате всеки като модел самостоятелно за заявки или други операции, тъй като Ak47 автоматично ще приложи __t стойност във всички заявки/актуализации.

Така че въпреки че хранилището е в една колекция, може да изглежда, че има много колекции, но също така има предимството да ги съхранява заедно за други полезни операции. Ето как можете да приложите вида "полиморфизъм", който търсите.




  1. Redis
  2.   
  3. MongoDB
  4.   
  5. Memcached
  6.   
  7. HBase
  8.   
  9. CouchDB
  1. Преобразуване на BSON в JSON документ в Java

  2. Пагинация с диапазон на MongoDB

  3. MongoDB $first Aggregation Pipeline Operator

  4. Mongodb сумира размера на полетата на масива

  5. Дублирайте документ в MongoDB, като използвате нов _id