Mongoose needs to create objects, but skip the property if another object already has this property

好久不见. 提交于 2019-12-12 03:28:12

问题


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

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!