MongoDB
 sql >> Baza danych >  >> NoSQL >> MongoDB

Wiele odniesień do schematów w pojedynczej tablicy schematów — mangusta

To, czego szukasz tutaj, to mangusta .discriminator() metoda. Zasadniczo pozwala to na przechowywanie obiektów różnych typów w tej samej kolekcji, ale posiadanie ich jako odróżnialnych obiektów pierwszej klasy.

Pamiętaj, że zasada „tej samej kolekcji” jest ważna dla sposobu, w jaki .populate() prace i definicja referencji w modelu zawierającym. Ponieważ naprawdę możesz wskazać tylko „jeden” model jako odniesienie, istnieje jednak inna magia, która może sprawić, że jeden model pojawi się w wielu.

Przykładowa lista:

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

I wyjście

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

Możesz także odkomentować mongoose.set("debug",true) na liście, aby zobaczyć, jak mangusta faktycznie konstruuje połączenia.

To pokazuje, że możesz zastosować różne schematy do różnych obiektów pierwszej klasy, a nawet z różnymi metodami dołączonymi do nich, tak jak prawdziwe obiekty. Mongoose przechowuje je wszystkie w kolekcji „pistoletów” z dołączonym modelem i będzie zawierać wszystkie „typy” wskazane przez dyskryminator:

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

Ale także każdy inny „typ” jest w szczególny sposób odwoływany do własnego modelu. Widzisz więc, że kiedy mangusta przechowuje i odczytuje obiekt, istnieje specjalny __t pole, które mówi mu, który „model” zastosować, a tym samym dołączony schemat.

Jako jeden przykład nazywamy .shoot() metody, która jest definiowana inaczej dla każdego modelu/schematu. Możesz także nadal używać każdego jako modelu dla zapytań lub innych operacji, ponieważ Ak47 automatycznie zastosuje __t wartość we wszystkich zapytaniach/aktualizacjach.

Tak więc, chociaż przechowywanie znajduje się w jednej kolekcji, może wydawać się, że jest to wiele kolekcji, ale ma również tę zaletę, że przechowuje je razem do innych przydatnych operacji. W ten sposób możesz zastosować rodzaj „polimorfizmu”, którego szukasz.




  1. Redis
  2.   
  3. MongoDB
  4.   
  5. Memcached
  6.   
  7. HBase
  8.   
  9. CouchDB
  1. Jakie jest zalecane podejście do wielodostępnych baz danych w MongoDB?

  2. Zaplanuj pracę Node.js co pięć minut

  3. MongoDB :znajdź wartość w tablicy z wieloma kryteriami

  4. Przypadki użycia updateOne nad findOneAndUpdate w MongoDB

  5. MongoDB — nieautoryzowany użytkownik administratora