如何忽略对象中其他字段的重复属性?

时间:2016-03-26 20:21:01

标签: node.js mongodb mongoose mongodb-query

我写了一个for循环,它接受一个数据表并使用这个模式创建3,500个对象:

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

var LocationSchema = new Schema({
  twp: {type: String, index: true, unique: true, dropDups: true},
  rge: {type: String, unique: true},
});


module.exports = mongoose.model('Location', LocationSchema);

让我们说这是第一个创建的对象:

{
    "_id" : ObjectId("56f5eb02683e79de61278449"),
    "rge" : "008W",
    "twp" : "004S",
    "__v" : 0
}

如果使用值twp: 004S实例化任何其他对象,我希望仍然创建该对象,但是没有twp的值。它看起来像这样:

{
    "_id" : ObjectId("56f5eb02683e79de61274949"),
    "rge" : "009E",
    "__v" : 0
}

正如您所看到的,我尝试添加unique和dropDups,但这仍然创建了具有相同twp值的多个对象。我还尝试添加以下代码(根据某人的推荐),但结果仍然相同。

var twpSet = new Set();

LocationSchema.methods.twp1 = function () {
    var curTwp = this.twp;

    if (twpSet.has(curTwp)) {
        this.twp = undefined; // remove the twp field once duplicated
    } else {
        twpSet.add(curTwp); // save the existing twp value
    }
};

LocationSchema.queue('twp1');

1 个答案:

答案 0 :(得分:0)

问题是因为如果您没有在文档中包含特定字段但该字段上有一个"unique"索引,那么仍然需要考虑该字段的值为{ {1}}。

引用:

  

如果文档没有字段值,则该项的索引条目在包含它的任何索引中都将为null。因此,在许多情况下,您需要将唯一约束与稀疏选项组合在一起。稀疏索引会跳过缺少索引字段的任何文档,而不是为索引条目存储null。由于唯一索引不能具有字段的重复值,因此没有稀疏选项,MongoDB将拒绝没有索引字段的第二个文档和所有后续文档。

要解决此问题,请使用创建的索引上的"sparse"属性。 Heres的演示展示了两种情况:

null

代码注定会出错,但输出会显示会发生什么:

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


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

var sparseSchema = new Schema({
  "a": { "type": String, "unique": true, "sparse": true },
  "b": { "type": String, "unique": true }
});

var Sparse = mongoose.model('Sparsetest',sparseSchema);


async.eachSeries(
  [{ "a": 1, "b": 2 },{ "a": 2 },{ "b": 3 },{ "b": 4 },{ "a": 3 }],
  function(item,callback) {
    Sparse.create(item,function(err,doc) {
      console.log(doc);
      callback(err);
    });
  },
  function(err) {
    if (err) throw err;
    mongoose.disconnect();
  }
);

所以创建的前四个文档的一切都很好。第一个文档具有两个属性的唯一值,第二个文档不重复Mongoose: sparsetests.ensureIndex({ a: 1 }) { unique: true, sparse: true, background: true } Mongoose: sparsetests.insert({ a: '1', b: '2', _id: ObjectId("56f706820c2db3902e557cff"), __v: 0 }) Mongoose: sparsetests.ensureIndex({ b: 1 }) { unique: true, background: true } { _id: 56f706820c2db3902e557cff, b: '2', a: '1', __v: 0 } Mongoose: sparsetests.insert({ a: '2', _id: ObjectId("56f706820c2db3902e557d00"), __v: 0 }) { _id: 56f706820c2db3902e557d00, a: '2', __v: 0 } Mongoose: sparsetests.insert({ b: '3', _id: ObjectId("56f706820c2db3902e557d01"), __v: 0 }) { _id: 56f706820c2db3902e557d01, b: '3', __v: 0 } Mongoose: sparsetests.insert({ b: '4', _id: ObjectId("56f706820c2db3902e557d02"), __v: 0 }) { _id: 56f706820c2db3902e557d02, b: '4', __v: 0 } Mongoose: sparsetests.insert({ a: '3', _id: ObjectId("56f706820c2db3902e557d03"), __v: 0 }) undefined ^ MongoError: E11000 duplicate key error collection: test.sparsetests index: b_1 dup key: { : null } ,第三个文档不重复"a"。值得注意的是,第三和第四个文档不包含"b"属性,但由于该属性被"a"索引,因此这不是问题。

虽然"sparse"属性不同,但当我们尝试插入另一个文档时,该属性被视为"b",则会为该索引抛出重复键错误。即使null属性仍然是唯一的,"a"已经有"b",所以它不是。{/ p>

因此,如果您想要null索引,但不打算在每个文档中包含该属性,则必须启用"unique"

N.B {@ 1}}选项已被弃用,而且#34; no-op"在任何发布过MongoDB 3.x.无论如何,从集合中删除现有的重复项绝不是一个好的选择。如果您存在重复数据,则需要手动过程将其删除。