带有日期的猫鼬混合类型字段 [英] Mongoose Mixed type field with dates

查看:52
本文介绍了带有日期的猫鼬混合类型字段的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在创建一个应用程序,用户可以在其中创建各种类型的自定义字段,我想将这些字段存储在 mongo 中.类型将包括字符串、数字和日期.我的架构如下所示:

I'm creating an app where a user can create various types of custom fields, and I'd like to store those fields in mongo. The types will include String, Number, and Date. My schema looks like this:

const MetaSchema = new mongoose.Schema({
  key: String,
  value: {type: mongoose.Schema.Types.Mixed},
  type: String,
  created_at: {type: Date, default: Date.now}
});

这很好用,我可以按预期存储我的数据.问题是,例如,当我想存储一个以 ISO 格式发送到服务器的日期时,有效负载可能如下所示:

This works great, and I can store my data as expected. The issue is, when I want to store a date for instance, that gets sent across to the server in ISO format, a payload that might look like:

{
  "key": "Contract Signed",
  "value": "2016-04-06T22:35:11.540Z",
  "type": "date"
}

有什么办法可以让 mongo/mongoose 把它当作日期而不是字符串来处理和存储?如果我将其设置为输入日期,那么我认为它可以解决问题,但我必须保存他们可以为自定义字段提供的几乎所有内容.非常感谢!

Any way I can get mongo / mongoose to treat and store this like a date instead of a string? If I set this to type date then I think it would do the trick, but I have to save just about anything they can come up with for custom fields. Thanks so much!

TLDR:是否可以根据插入的数据类型(IE 日期与字符串)对 mongoose/mongo 中的混合数据类型进行不同处理.

TLDR: Can a mixed data type in mongoose / mongo be treated differently based on the type of data being inserted (IE Date vs String).

推荐答案

使用 mongoose discriminators 是可能是去这里的方式.他们实际上在存储的文档中使用他们自己的类型"(默认 __t ,但可以被覆盖)属性,这允许 mongoose 将一种模型"实际应用于每个具有自己附加架构的对象.

Using mongoose discriminators is probably the way to go here. They actually work with their own "type" ( default __t but can be overridden ) property within the stored documents which allows mongoose to actually apply a kind of "model" to each object with it's own attached schema.

举个简单的例子:

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

mongoose.connect('mongodb://localhost/things');
mongoose.set("debug",true);

function BaseSchema() {

  Schema.apply(this,arguments);

  this.add({
    key: String,
    created_at: { type: Date, default: Date.now }
  });

}

util.inherits(BaseSchema,Schema);

var metaSchema = new BaseSchema();

var stringSchema = new BaseSchema({
  value: String
});

var numberSchema = new BaseSchema({
  value: Number
});

var dateSchema = new BaseSchema({
  value: Date
});

var MetaModel = mongoose.model('MetaModel',metaSchema),
    StringModel = MetaModel.discriminator('StringModel', stringSchema),
    NumberModel = MetaModel.discriminator('NumberModel', numberSchema),
    DateModel = MetaModel.discriminator('DateModel', dateSchema);

async.series(
  [
    function(callback) {
      MetaModel.remove({},callback);
    },
    function(callback) {
      async.each(
        [
          { "model": "StringModel", "value": "Hello" },
          { "model": "NumberModel", "value": 12 },
          { "model": "DateModel", "value": new Date() }
        ],
        function(item,callback) {
          mongoose.model(item.model).create(item,callback)
        },
        callback
      );
    },
    function(callback) {
      MetaModel.find().exec(function(err,docs) {
        console.log(docs);
        callback(err);
      });
    },
    function(callback) {
      DateModel.findOne().exec(function(err,doc) {
        console.log(doc);
        callback(err);
      });
    }
  ],
  function(err) {
    if (err) throw err;
    mongoose.disconnect();
  }
)

因此,由于这些基本上是相关的",因此我定义了一个具有公共元素的基本"模式.当然,每种类型"都有单独的模式.核心模型"的实际分配发生在以下几行:

So since these are basically "related" I am defining a "Base" schema with the common elements. Then of course there are separate schemas for each "type". The actual assignment to the core "model" happens in these lines:

var MetaModel = mongoose.model('MetaModel',metaSchema),
    StringModel = MetaModel.discriminator('StringModel', stringSchema),
    NumberModel = MetaModel.discriminator('NumberModel', numberSchema),
    DateModel = MetaModel.discriminator('DateModel', dateSchema);

这意味着 MetaModel 实际上定义了集合和默认"模式分配.以下几行使用该模型中的 .discriminator() 来定义将存储在同一集合中的其他类型"文档.

This means that MetaModel actually defines the collection and "default" schema assingment. The following lines use .discriminator() from that model in order to define the other "types" of documents that will be stored in the same collection.

随着调试输出显示正在发生的事情,清单产生如下内容:

With the debugging output on to show what is happening, the listing produces something like this:

Mongoose: metamodels.remove({}) {}
Mongoose: metamodels.insert({ value: 'Hello', __t: 'StringModel', created_at: new Date("Thu, 07 Apr 2016 00:24:08 GMT"), _id: ObjectId("5705a8a8443c0f74491bdec0"), __v: 0 })
Mongoose: metamodels.insert({ value: 12, __t: 'NumberModel', created_at: new Date("Thu, 07 Apr 2016 00:24:08 GMT"), _id: ObjectId("5705a8a8443c0f74491bdec1"), __v: 0 })
Mongoose: metamodels.insert({ value: new Date("Thu, 07 Apr 2016 00:24:08 GMT"), __t: 'DateModel', created_at: new Date("Thu, 07 Apr 2016 00:24:08 GMT"), _id: ObjectId("5705a8a8443c0f74491bdec2"), __v: 0 })
Mongoose: metamodels.find({}) { fields: undefined }
[ { created_at: Thu Apr 07 2016 10:24:08 GMT+1000 (AEST),
    __t: 'StringModel',
    __v: 0,
    value: 'Hello',
    _id: 5705a8a8443c0f74491bdec0 },
  { created_at: Thu Apr 07 2016 10:24:08 GMT+1000 (AEST),
    __t: 'NumberModel',
    __v: 0,
    value: 12,
    _id: 5705a8a8443c0f74491bdec1 },
  { created_at: Thu Apr 07 2016 10:24:08 GMT+1000 (AEST),
    __t: 'DateModel',
    __v: 0,
    value: Thu Apr 07 2016 10:24:08 GMT+1000 (AEST),
    _id: 5705a8a8443c0f74491bdec2 } ]
Mongoose: metamodels.findOne({ __t: 'DateModel' }) { fields: undefined }
{ created_at: Thu Apr 07 2016 10:24:08 GMT+1000 (AEST),
  __t: 'DateModel',
  __v: 0,
  value: Thu Apr 07 2016 10:24:08 GMT+1000 (AEST),
  _id: 5705a8a8443c0f74491bdec2 }

您可以看到所有内容都在分配给主模型的 metamodels 集合中创建,但是在引用每个鉴别器模型"时,会自动创建一个 __t 字段包括型号名称.这将在稍后读回数据时使用,以便猫鼬知道在投射对象时应用哪个模型和附加模式.

You can see that everything is being created in the metamodels collection assigned to the main model, however when referencing each "discriminator model" there is a __t field automatically created that includes the model name. This will be used later on reading the data back so mongoose knows which model and attached schema to apply when casting the objects.

当然,由于这些都有自己的架构,因此适用标准验证规则.此外,附加到每种类型的模式的任何实例方法"也适用于任何单独的模型.

Naturally since these all have their own schema, the standard validation rules apply. In addition any "instance methods" attached to the schema for each type also apply just as it would with any separate model.

最后,__t 字段也适用于使用鉴别器模型"之一进行任何其他操作,例如查询或更新.如上次执行的语句所示:

Finally, that __t field is also applied with using one of the "discriminator models" for any other operation such as query or update. As shown in the last executed statement:

      DateModel.findOne().exec(function(err,doc) {
        console.log(doc);
        callback(err);
      });

和实际调用:

Mongoose: metamodels.findOne({ __t: 'DateModel' }) { fields: undefined }

自动包含该属性值以指示类型"并提供集合数据的虚拟视图",就好像它只包含该特定类型一样.

That property value is included automatically to indicate the "type" and give a "virtual view" of the collection data just as if it only contained that particular type.

真正的力量实际上在于所有对象都在同一个集合中,以及猫鼬在检索数据时自动分配类类型"的能力.

The real power actually lies in all objects being in the same collection and the ability of mongoose to assign the "class type" automatically on retrieval of data.

这篇关于带有日期的猫鼬混合类型字段的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆