MongoDB
 sql >> Teknologi Basis Data >  >> NoSQL >> MongoDB

Beberapa referensi skema dalam array skema tunggal - luwak

Apa yang Anda cari di sini adalah .discriminator() mon luwak metode. Ini pada dasarnya memungkinkan Anda untuk menyimpan objek dari tipe yang berbeda dalam koleksi yang sama, tetapi menjadikannya sebagai objek kelas satu yang dapat dibedakan.

Perhatikan bahwa prinsip "koleksi yang sama" di sini penting untuk bagaimana .populate() karya dan definisi referensi dalam model yang berisi. Karena Anda benar-benar hanya dapat menunjuk ke "satu" model untuk referensi, tetapi ada beberapa keajaiban lain yang dapat membuat satu model muncul sebanyak mungkin.

Contoh daftar:

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

Dan keluaran

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"
  }
]

Anda juga dapat menghapus komentar mongoose.set("debug",true) baris dalam daftar untuk melihat bagaimana luwak sebenarnya membuat panggilan.

Jadi apa yang ditunjukkan ini adalah bahwa Anda dapat menerapkan skema yang berbeda ke objek kelas satu yang berbeda, dan bahkan dengan metode berbeda yang melekat padanya seperti objek nyata. Luwak menyimpan semua ini dalam koleksi "senjata" dengan model terlampir, dan itu akan berisi semua "jenis" yang dirujuk oleh pembeda:

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

Tetapi juga setiap "tipe" yang berbeda direferensikan dengan modelnya sendiri dengan cara yang khusus. Jadi Anda melihat bahwa ketika luwak menyimpan dan membaca objek, ada __t khusus bidang yang memberi tahu "model" mana yang akan diterapkan, dan karenanya skema terlampir.

Sebagai salah satu contoh kita memanggil .shoot() metode, yang didefinisikan berbeda untuk setiap model/skema. Dan Anda juga masih dapat menggunakan masing-masing sebagai model dengan sendirinya untuk kueri atau operasi lainnya, karena Ak47 akan secara otomatis menerapkan __t nilai di semua kueri/pembaruan.

Jadi, meskipun penyimpanan dalam satu koleksi, itu bisa tampak seperti banyak koleksi, tetapi juga memiliki manfaat untuk menyatukannya untuk operasi berguna lainnya. Ini adalah bagaimana Anda dapat menerapkan jenis "polimorfisme" yang Anda cari.




  1. Redis
  2.   
  3. MongoDB
  4.   
  5. Memcached
  6.   
  7. HBase
  8.   
  9. CouchDB
  1. Data pembaruan MongoDB di bidang bersarang

  2. Bagaimana cara menggunakan agregasi MongoDB untuk pagination?

  3. Bagaimana cara menanyakan mongodb dengan DBRef

  4. Sistem file read-only saat mencoba mkdir /data/db di Mac

  5. Argumen yang diteruskan harus berupa string 24 karakter hex - saya pikir itu