确保只有一个数组元素具有给定属性

时间:2015-10-07 19:51:52

标签: javascript mongodb meteor

我想在包含数组的集合上设置布尔标志。作为数据的一个例子:

{
  _id: "12341234",
  name: {
    first: 'Jeff',
    last: 'Jefferson'
  },
  emails: [{
    address: 'fake@fake.org',
    verified: true,
    primary: true
  }, {
    address: 'fake@fake.net',
    verified: true,
    primary: false
  }]
}

在此表中的每个条目中,我希望电子邮件数组只有一个primary: true条目。

使用表格中的键,您可以执行以下操作以确保唯一性:

Meteor._ensureIndex({ 'name.last': 1 }, { unique: 1 });

是否有办法在单个条目中对数组执行此操作?

1 个答案:

答案 0 :(得分:1)

看看使用aldeed添加自定义验证:simple-schema,使用aldeed附加到您的集合:collections2

customUsers = new Mongo.Collection('customUsers');
customUsers.attachSchema(new SimpleSchema({

  name: {
    type: new SimpleSchema({
      first: { type: String},
      last:  { type: String},
    }),
  },

  emails: {
    type: Array,
    custom: function() {
      if (_.compact(_.pluck(this.value, 'primary')).length !== 1) {
        return 'NotOnePrimaryEmail';
      }
    },
  },
  'emails.$': {
    type: Object,
  },
  'emails.$.address': {
    type: String,
    regEx: SimpleSchema.RegEx.Email,
  },
  'emails.$.verified': {
    type: Boolean,
  },
  'emails.$.primary': {
    type: Boolean,
  },

}));

SimpleSchema.messages({
  NotOnePrimaryEmail: 'You must have one, and only one, email marked as primary',
});

if (Meteor.isServer) {
  Meteor.startup(function() {

    objValid = {
      name: {
        first: 'Jeff',
        last: 'Jefferson',
      },
      emails: [{
        address: 'fake@fake.org',
        verified: true,
        primary: true,
      }, {
        address: 'fake@fake.net',
        verified: true,
        primary: false,
      },],
    };

    objNoPrimary = {
      name: {
        first: 'Jeff',
        last: 'Jefferson',
      },
      emails: [{
        address: 'fake@fake.org',
        verified: true,
        primary: false,
      }, {
        address: 'fake@fake.net',
        verified: true,
        primary: false,
      },],
    };

    objMultiplePrimary = {
      name: {
        first: 'Jeff',
        last: 'Jefferson',
      },
      emails: [{
        address: 'fake@fake.org',
        verified: true,
        primary: true,
      }, {
        address: 'fake@fake.net',
        verified: true,
        primary: true,
      },],
    };

    [objValid, objNoPrimary, objMultiplePrimary].forEach(
      function(obj) {
        try {
          customUsers.insert(obj);
          console.log('Object was valid, inserted into collection');
        } catch (err) {
          console.log('Error: ' + err.sanitizedError.reason);
        }
      }
    );
  });
}

服务器控制台的输出:

~/test/schema$ meteor
[[[[[ ~/test/schema ]]]]]                     

=> Started proxy.                             
=> Started MongoDB.                           
=> Started your app.                          

=> App running at: http://localhost:3000/
I20151008-15:04:15.280(13)? Object was valid, inserted into collection
I20151008-15:04:15.281(13)? Error: You must have one, and only one, email marked as primary
I20151008-15:04:15.281(13)? Error: You must have one, and only one, email marked as primary