【问题标题】:Add uppercase: true to mongoose embedded document为猫鼬嵌入文档添加大写:true
【发布时间】:2015-12-08 01:39:25
【问题描述】:

如果我有两个架构,一个将嵌入另一个:

var mongoose = require("mongoose");
var Schema = mongoose.Schema;

// Will embed this in the personSchema below
var addressSchema = new Schema({
    street: String,
    city: String,
    state: {
        type: String,
        uppercase: true
    },
    zip: Number
});

var personSchema = new Schema({
    firstName: {
        type: String,
        required: true
    },
    lastName: {
        type: String,
        required: true
    },
    emailAddress: {
        type: String,
        lowercase: true
    },
    phoneNumber: Number,
    address: addressSchema
});

module.exports = mongoose.model("Person", personSchema);

我似乎无法让 uppercase: true 用于嵌入文档 - 不会引发错误,但它根本不会大写 state 属性。或任何类似的选项。

我一直在搜索 Mongoose 文档,但也许我只是没有找到它提到在子文档上设置这些类型的附加选项不起作用的地方。

【问题讨论】:

  • 您说:“我似乎无法获取大写:适用于嵌入式文档的 true”但错误是什么?
  • 您可以使用的一件事是Parent.pre("save", function(next){ "make it uppercase here!" }) 挂钩并“手动”执行(如果您在此期间找不到解决方案)。查看此帖子:stackoverflow.com/questions/14023937/…
  • 对不起,我不是很明确。没有抛出错误,它只是没有将“状态”大写。我在父架构上对其进行了测试,它工作得很好,我也在子架构上尝试了lowercase,但无济于事。
  • 除了我上面建议的可能性之外,请阅读此post,这可能可以解释为什么它不会变成大写...
  • @nbro 预保存挂钩不起作用,我认为这是因为我没有在 Mongo 自己的集合中保存新的 Child,我只是保存了 @987654328 @。所以我认为Child.pre("save") 事件永远不会被触发。还有其他想法吗?我应该用另一个钩子来代替save吗?

标签: node.js mongodb mongoose embedded-documents


【解决方案1】:

直到最近,如果您尝试像您正在做的那样直接将一个架构嵌入到另一个架构中,Mongoose 会抛出异常。看起来它现在得到了部分支持,但显然不适用于这种情况。

您可以通过仅使用来自addressSchema 的定义对象而不是personSchemaaddress 字段的定义中的架构本身来使其工作。

var addressObject = {
    street: String,
    city: String,
    state: {
        type: String,
        uppercase: true
    },
    zip: Number
};
var addressSchema = new Schema(addressObject);

var personSchema = new Schema({
    firstName: {
        type: String,
        required: true
    },
    lastName: {
        type: String,
        required: true
    },
    emailAddress: {
        type: String,
        lowercase: true
    },
    phoneNumber: Number,
    address: addressObject
});

【讨论】:

  • 我不太确定它是否真的那么新。这是docs from version 2.7 谈论通过创建单独的模式并使用该模式进行嵌入来嵌入文档。据我所知,这样做的唯一好处(假设您没有将它用作带有 ObjectId 的引用)是它为您的嵌入式文档提供了自己的 _id 属性。但显然你失去了额外的验证。我刚刚检查过,你的方式肯定有效,但现在我很困惑为什么要嵌入模式而不是对象文字,除了 id 东西
  • @bobbyz 这些文档仅适用于嵌入文档 arrays,而不是像您在这里所做的单个子文档。
  • 啊,有道理。而且我刚刚注意到最新的 mongoose 文档确实说嵌入单个模式实例是 4.2 的新内容。因此,似乎不对嵌入式数据执行对象文字的唯一原因是您是否需要该嵌入式数据具有_ids?如果您需要 _ids,您可能需要将关系设置为对另一个集合的引用。这听起来像是一个非常合理的结论吗?
  • @bobbyz 是的,我同意这一点。或者您只想在模块中公开模式以进行嵌入,或者您只能访问模式,或类似的东西。
【解决方案2】:

不确定这是否是最好的方法,但我添加了一个预保存钩子(根据 cmets 中 @nbro 的建议),这似乎有效:

var addressSchema = new Schema({
    street: String,
    city: String,
    state: {
        type: String,
        uppercase: true
    },
    zip: Number
});

addressSchema.pre("save", function (next) {
    this.state = this.state.toUpperCase();
    next();
});

var personSchema = new Schema({
    firstName: {
        type: String,
        required: true
    },
    lastName: {
        type: String,
        required: true
    },
    emailAddress: {
        type: String,
        lowercase: true
    },
    phoneNumber: Number,
    address: addressSchema
});

更新 #1:

我似乎能够找到很多人在没有任何额外验证 (required: true) 或更改 (uppercase: true) 的情况下嵌入简单模式的案例。虽然上述解决方案确实有效,但似乎没有必要。我可能应该做的只是放入对象文字以嵌入信息:

var personSchema = new Schema({
    ...
    address: {
        street: String,
        city: String,
        state: {
            type: String,
            uppercase: true
        },
        zip: Number
    }
});

似乎使用单独架构的唯一充分理由是,如果您绝对需要嵌入数据具有_id 属性并且您不需要向任何属性添加额外的验证或更改选项。如果您需要_id,我猜您可能不应该嵌入数据,而是将其保存为单独的对象并进行引用。

当我发现新信息和最佳实践时,我会不断更新。

更新 #2:

如果您想在嵌入文档中包含验证,例如使 address 属性成为必需,您将不得不单独进行,如 this very good blog post about it 中所述。

【讨论】:

    猜你喜欢
    • 2016-06-08
    • 2015-09-06
    • 1970-01-01
    • 1970-01-01
    • 2012-04-29
    • 1970-01-01
    • 1970-01-01
    • 2016-11-28
    相关资源
    最近更新 更多