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

Node.js 如何忽略对象中其他字段的重复属性?,node.js,mongodb,mongoose,mongodb-query,Node.js,Mongodb,Mongoose,Mongodb Query,我编写了一个for循环,它获取一个数据表,并使用此模式创建3500个对象: 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}, }); mo

我编写了一个for循环,它获取一个数据表,并使用此模式创建3500个对象:

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和dropdup,但这仍然创建了具有相同
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');

问题在于,如果文档中没有包含特定字段,但该字段上有索引,则出于索引目的,仍然会考虑该字段的值为
null

引文:

如果文档没有字段值,则该项的索引项在包含该字段的任何索引中都将为空。因此,在许多情况下,您将希望将唯一约束与稀疏选项相结合。稀疏索引跳过任何缺少索引字段的文档,而不是为索引项存储null。由于唯一索引的字段不能有重复的值,如果没有稀疏选项,MongoDB将拒绝第二个文档以及没有索引字段的所有后续文档

要解决此问题,请使用已创建索引上的属性。下面是一个演示,展示了这两种情况:

var async=require('async'),
mongoose=require('mongoose'),
Schema=mongoose.Schema;
mongoose.set(“调试”,true);
猫鼬mongodb://localhost/test');
var sparseSchema=新模式({
“a”:{“type”:String,“unique”:true,“sparse”:true},
“b”:{“type”:字符串,“unique”:true}
});
var Sparse=mongoose.model('Sparsetest',sparseSchema);
async.eachSeries(
[{“a”:1,“b”:2},{“a”:2},{“b”:3},{“b”:4},{“a”:3}],
函数(项,回调){
创建(项目、函数(错误、文档){
控制台日志(doc);
回调(err);
});
},
功能(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})
猫鼬:sparsetests.ensureIndex({b:1}){唯一:真,背景:真}
{id:56F70620C2DB3902E557CFF,b:'2',a:'1',u v:0}
Mongoose:sparsetests.insert({a:'2',_id:ObjectId(“56f706820c2d3902e557d00”),__v:0})
{id:56F70620C2DB3902E557D00,a:'2','v:0}
Mongoose:sparsetests.insert({b:'3',_id:ObjectId(“56f706820c2d3902e557d01”),_v:0})
{id:56F70620C2DB3902E557D01,b:'3',uu v:0}
Mongoose:sparsetests.insert({b:'4',_id:ObjectId(“56f706820c2d3902e557d02”),__v:0})
{id:56F70620C2DB3902E557D02,b:'4',uu v:0}
Mongoose:sparsetests.insert({a:'3',_id:ObjectId(“56f706820c2d3902e557d03”),__v:0})
未定义
^
MongoError:E11000重复密钥错误集合:test.sparsetests索引:b_1重复密钥:{:null}
因此,对于创建的前四个文档,一切都很好。第一个文档对这两个属性都有唯一的值,第二个文档不重复
“a”
,第三个和第四个文档不重复
“b”
。值得注意的是,这里的第三个和第四个文档不包含
“a”
属性,但是由于该属性是
“稀疏的”
索引的,所以这不是问题

但是
“b”
属性的情况并非如此,当我们尝试插入另一个文档,其中该属性被视为
null
时,会为该索引抛出重复键错误。即使
“a”
属性仍然是唯一的,
“b”
已经具有
null
,因此它不是唯一的

因此,如果您想要一个
“唯一的”
索引,但不打算在每个文档中包含该属性,则必须启用
“稀疏”


N.B不推荐使用
“dropDups”
选项,并且在MongoDB 3.x之前的任何版本中都会出现“no op”。无论如何,从集合中删除现有副本从来都不是一个好的选择。如果存在重复数据,则需要手动过程将其删除。

因此,为了实现这一点,我所要做的就是将
sparse:true
添加到我的模式中?我试过了,但不太管用。试图在谷歌上搜索更多关于稀疏信息的信息。@fresh5447不仅有相关信息的超链接(和引文),而且还有一个工作示例向您说明错误所在。所以你不可能很努力的。再仔细阅读一遍,看看你的代码哪里出了问题。如果希望从任何文档中“省略”它的字段是唯一的,则该字段需要有
稀疏的
。否则它是重复的
null
。可能是重复的?也许更新原始问题比在SO中给出另一个相同的问题更好?