0

refererencing an answer here: https://stackoverflow.com/a/22680973/9817602

Expected result: when saving document in my database, all documents are unique.

strategy: using function that registers the document once then update it progressively.

problem: the very first recording create a new property, but then the next Model.save() of the property create an identic property instead of merging the value inside a same property - for example , with the timePlot 9 in my model.

trials to resolve the problem:

  • handle the location of the first saving using different methods:
    • push(),
    • directly assign my value like property={}.

current results -note the duplicate on timePlot:"9" 's property:

     {
        "prospect": [
            {
                "$oid": "5c901344e3da317e2838482a"
            },
            {
                "$oid": "5c90134be3da317e2838482d"
            }
        ],
        "_id": {
            "$oid": "5c901338e3da317e28384828"
        },
        "timePlot": "9"
    },
    {
        "prospect": [
            {
                "$oid": "5c901338e3da317e28384826"
            }
        ],
        "_id": {
            "$oid": "5c901338e3da317e28384829"
        },
        "timePlot": "9"
    }

my server.js snippet:

 let  scheduleInstance = new ScheduleMongoose(schedule) 
            let scheduleDocument = await ScheduleMongoose.findOne({day}, (err, data) =>{ 
                if(err) throw console.error(err)
                    // console.log("data ScheduleMongoose.findOne: ", data)
                return data 
            })
            if (scheduleDocument){ 
                // console.log("schedule found:", scheduleDocument);
                scheduleDocument.hour[daySlot].time.some(({timePlot}, i) =>{ 
                    if( timePlot=== hour[daySlot].time.timePlot) {
                        match=true;
                        console.log("timePlot match with time, updating timeProspectIndex...");
                        timeProspectIndex=i;
                        console.log("time prospect update");
                    }
                    return timePlot=== hour[daySlot].time.timePlot
                })
                scheduleInstance=scheduleDocument;
            }


             // time property exists => update object
            if( 
                match &&
                scheduleInstance.hour[daySlot].time.length>0 &&
                scheduleInstance.hour[daySlot].time[timeProspectIndex].prospect
            ){
                console.log("line 326 scheduleInstance.hour[daySlot].time[timeProspectIndex]: ",
                    scheduleInstance.hour[daySlot].time[timeProspectIndex]
                )


                console.log("\n object => inserting new prospect...")
                scheduleInstance.hour[daySlot].time[timeProspectIndex].prospect.push(prospect._id);
                console.log("object => insert new prospect succeed \n")   
            }  
            // new time property with sibling object => insert at end of array          
            else if (
                !match && 
                scheduleInstance.hour[daySlot].time.length>0 &&
                scheduleInstance.hour[daySlot].time[timeProspectIndex].length >0
            ){  
                    console.log(" \n adding new timeslot...") 
                    timeProspectIndex=scheduleInstance.hour[daySlot].time.length; 
                    scheduleInstance.hour[daySlot].time[timeProspectIndex]={
                        prospect: prospect._id,
                        timePlot: hour[daySlot].time.timePlot
                    } 
                    console.log("adding timeslot succeed \n")
            }
            // very new object in database => create property
            else{
                console.log("\n create time property...")
                let timeProspectIndex=0 

                let timeData={
                    prospect: prospect._id,
                    timePlot: hour[daySlot].time.timePlot
                } 
                scheduleInstance.hour[daySlot].time.push(timeData) 
                console.log("create time property succeed \n")
            }

***edit: ***currently I'm trying the following:

 var schedule= {
    month,
    day,
    hour
 };
 var update ={
     prospect: prospect._id,
     timePlot: hour[daySlot].time.timePlot
 };

        console.log("line 353  _ schedule.hour[daySlot]: ",schedule.hour[daySlot])

        console.log("355 _ schedule.hour[daySlot].time: ", schedule.hour[daySlot].time)
        // console.log("bulkWrite: ScheduleMongoose", ScheduleMongoose)
        ScheduleMongoose.collection.bulkWrite([ 
            {
                updateOne:{
                    "filter": schedule.hour[daySlot].time.timePlot,  
                    "update":{
                        "$setOnInsert": { [schedule.hour[daySlot].time]:  update }
                    },
                    "upsert": true 
                }
            }, 
            {
                updateOne:{
                    "filter": schedule.hour[daySlot].time.timePlot, 
                    "update":{
                        "$addToSet": { [schedule.hour[daySlot].time]:  update }
                    },
                    "upsert": true 
                }
          }

        ]).then(res => {
            console.log("bulk succeed: ", res.insertedCount, res.modifiedCount, res.deletedCount);
            updateProspect(prospect, schedule)
        })
        .catch(err=>{ 
            return console.error(err) 
        })         

    }

returns me:

{ MongoError: BSON field 'update.updates.q' is the wrong type 'string', expected type 'object'

I can't figure out what is wrong, any hint would be great, thanks,

any hint would be great, thanks

Webwoman
  • 10,196
  • 12
  • 43
  • 87
  • 1
    In the part of the code you are not showing you are likely calling something like `let sheduleInstance = new Schedule()`. That creates a "new" object for insertion into the collection. You want to "update" or rather "upsert" where something does not exist as a document or "merge" where it does. The process for "upserting arrays" actually requires **three** write attempts, and preferably with [`bulkWrite()`](https://mongoosejs.com/docs/api.html#model_Model.bulkWrite) in modern releases. – Neil Lunn Mar 18 '19 at 23:54
  • yes I call `new Model()` above effectively – Webwoman Mar 19 '19 at 00:41
  • if I understand well only the most simple case can be handle with the `save()` method, then the other cases are preferably handled with the mongoose queries – Webwoman Mar 19 '19 at 13:37
  • Added [Upsert and $inc Sub-document in Array](https://stackoverflow.com/questions/55217447/upsert-and-inc-sub-document-in-array) since current edits still show the original referenced mistake but are closer in structure to the additional answer. Missing `$ne` on filter where the statement is `$push` and order of bulk operations – Neil Lunn Mar 24 '19 at 01:15

0 Answers0