问题
I know the title is confusing but let me explain more clearly.
Here is what my mongoose schema looks like:
var LocationSchema = new Schema({
locationKey: {type: String, unique: true},
wheat: Array,
barley: Array,
cty: {type: String, unique: true},
twp: {type: String, index: { unique: true} , dropDups: true},
rge: {type: String, unique: true},
});
I wrote some code that will create 3500 locations using this schema. The problem is that lots of locations have the same value for twp
. When this is the case, I need it to still create the object, but not create the twp
if any other object that has been created has the same twp
.
As you can see above I tried using the unique approach above. Here is two sample objects for more clarity:
Object One:
{
"_id" : ObjectId("56f5af9547a341720b0b25cd"),
"rge" : "034E",
"twp" : "001N",
"cty" : "003",
"locationKey" : "003001N034E",
"__v" : 0
}
If I am going to create a new object, that has twp: 001N
, I would like it to be created, but to look like so:
{
"_id" : ObjectId("56f5af9547a341720b0b25cd"),
"rge" : "034W",
"cty" : "004",
"locationKey" : "003001N034E",
"__v" : 0
}
In server JS I have an array of 3,000 objects, I am looping through this array to create a Location Object for each item like so:
locations.forEach(function(item){
var location = new Location();
location.locationKey = item.locationKey.trim();
location.cty = item.cty.trim();
location.twp = item.twp.trim();
location.rge = item.rge.trim();
location.wheat = item.wheat;
location.barley = item.barley;
location.save();
});
回答1:
To add methods pre creating schema, you could do it through schema.queue
per this discussion, here are the test codes under mongoose v4.4.6
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');
Test data
var l1 = new Loca({
locationKey: 'k1',
cty: 'c1',
twp: 't1',
rge: 'r1'
});
console.log(l1);
l1.save(function(err) {
if (err)
console.log(err);
else
console.log('save location1 successfully');
})
var l2 = new Loca({
locationKey: 'k2',
cty: 'c2',
twp: 't1',
rge: 'r2'
});
console.log(l2);
l2.save(function(err) {
if (err)
console.log(err);
else
console.log('save location2 successfully');
})
Results are
{ "_id" : ObjectId("56f5e484a22885dd0362a39a"), "locationKey" : "k1", "cty" : "c1", "twp" : "t1", "rge" : "r1", "barley" : [ ], "wheat" : [ ], "__v" : 0 }
{ "_id" : ObjectId("56f5e484a22885dd0362a39b"), "locationKey" : "k2", "cty" : "c2", "rge" : "r2", "barley" : [ ], "wheat" : [ ], "__v" : 0 }
Another option is to check the existing document before save
the new document through .pre('save'
middleware, if find the duplicate twp
, remove it in the new document, then save it.
LocationSchema.pre('save', function(next) {
var curTwp = this.twp;
console.log(curTwp);
var obj = this;
Loca.findOne({twp: curTwp}, function(err, loc) {
if (err)
next(err);
else if (loc) {
// find the duplicate twp before save
obj.twp = undefined;
next();
}else
next();
})
});
var Loca = mongoose.model('Loca', LocationSchema);
Test codes
var l1 = new Loca({
locationKey: 'k1',
cty: 'c1',
twp: 't1',
rge: 'r1'
});
var l2 = new Loca({
locationKey: 'k2',
cty: 'c2',
twp: 't1',
rge: 'r2'
});
console.log(l1);
l1.save(function(err) {
if (err)
console.log(err);
else {
l2.save(function(err) {
if (err)
console.log(err);
else
console.log('save location2 successfully');
})
}
})
Save result as above, to make sure your huge data is saved one by one, you could use async.series.
来源:https://stackoverflow.com/questions/36230055/mongoose-needs-to-create-objects-but-skip-the-property-if-another-object-alread