'Failed validation: The positional operator did not find the match needed from the query' when using updateAsync()

I’ve come across the error ‘Failed validation The positional operator did not find the match needed from the query.’ in a few different places in our codebase when trying to use updateAsync to set an object in the DB. It looks like the error is originating from the aldeed:collection2@4.1.4 package. I’m not sure if this is something I am doing wrong or if it’s an actual issue but any help is appreciated.

The schema:

const orderSchema = new SimpleSchema({
appointment: {
    type: Object,
    label: 'Appointment',
    optional: true,
    security: {
      public: false,
    }
  },
  'appointment.dateTime': {
    type: Date,
    label: 'Date and time of appointment',
    optional: true,
    security: {
      public: false,
    }
  },
  'appointment.date': {
    type: String,
    label: 'Date of appointment',
    optional: true,
    security: {
      public: false,
    }
  },
  'appointment.time': {
    type: String,
    label: 'Time of appointment',
    optional: true,
    security: {
      public: false,
    }
  },
  'appointment.type': {
    type: String,
    label: 'Type of appointment',
    allowedValues: ['appointment', 'walkin'],
    optional: true,
    security: {
      public: false,
    }
  },
  'appointment.notes': {
    type: String,
    label: 'Walk-in notes',
    optional: true,
    security: {
      public: false,
    }
  },
});

The updateAsync:


const appointmentData = {};

    if (appointment.type === 'appointment') {
      appointmentData.appointment = {
        dateTime: appointment.dateTime,
        date: appointment.date,
        time: appointment.time,
        type: appointment.type,
      };
    } else {
      appointmentData.appointment = {
        type: appointment.type,
        notes: appointment.notes
      };
    }

await Orders.updateAsync({
      _id: orderId
    }, {
      $set: appointmentData
    });

I’ve tried a few different syntax changes and ways of structuring the object but nothing seems to help.

The current workaround I have is to change the updateAsync to rawCollection().updateOne() but you lose out on the instant reactivity from Meteor when you using that so I’d like to find a solution to why our updateAsync’s are failing.

  • Meteor version: 3.2.2
  • Browser: chrome
  • aldeed:collection2@4.1.4
1 Like

Hi @kab,

I suppose in your orderSchema there are other fields besides appointment. Is that right?

Ok try this:

await Orders.updateAsync({
      _id: orderId
    }, {
      $set: { ...appointmentData }
    })

Your code could be simplified to this:

// considering that a missing field on appointment is treated as undefined, you can just take the appointment object and insert it. Undefined fields will not be inserted. This is not the same for NULL fields. But NULL fields would not pass through your schema anyway.
// Let's say your appointment object comes as not an appointment and it would look like:

appointment = {
     type: 'something',
     notes: 'here are the notest'
}
// similarly if it comes the other way.

just do $set: { appointment }
Also the word ‘appointment’ is a bit too long to save it thousands of times in the DB. It is not efficient. You could use letters or numbers for the types.

1 Like

Here is the explanation from Perplexity AI:

In MongoDB, when app is an object, the difference between $set: app and $set: { app } is as follows:

  • $set: app

    • Incorrect syntax for MongoDB.
      • The $set operator expects an object where each key is the field to update and its value is the new value[1][5][6].
      • If you use $set: app and app is itself an object, MongoDB will not treat this as valid syntax and will likely throw an error or not update as expected because the update document structure is invalid.
      • Example: If app = { name: 'myApp', version: 1 }, then $set: app is not a valid MongoDB update operation.
  • $set: { app }

    • Correct syntax for MongoDB.
      • This is shorthand for $set: { app: app } (or $set: { app: { name: 'myApp', version: 1 } }).
      • It sets (or replaces) a field named app in your document to the value of the object app.
      • Example: If app = { name: 'myApp', version: 1 }, then $set: { app } will set the app field to { name: 'myApp', version: 1 } in your document[1][5][8].

Summary Table

Expression Effect in MongoDB
$set: app Invalid syntax, will not work as intended
$set: { app } Sets the field app to the value of the object app

If you want to spread the properties of app as top-level fields, you would use $set: { ...app } (in JavaScript), which would set each property of app as a top-level field in your document. But in pure MongoDB syntax, you would specify each field explicitly in the $set object.

1 Like

Thanks for the response and information. I tried the syntax you recommended in a few different ways and I’m still seeing the positional operator error. I noticed that if I remove the schema, it completes the insert without any errors.

I’m going to spin up an example app this week to see if I can reproduce the error. I’ll link it here when I’m finished.

This is why I asked you if you had anything else in the schema besided appointment. Even if you do, would be great to pull out the schema of appointment and define it as a new schema

const Appointment = new SimpleSchema({
   dateTime: ....,
   date: .....
   ...........
})

const orderSchema = new SimpleSchema({
   appointment: Appointment,
   somethingElse: ......
})


I tried separating the schemas, still no luck. I also tried out a few more syntax changes with the update and schemas and I’m still seeing the error.

I created an example app that uses aldeed:collection2@4.1.4 and aldeed:simple-schema@2.0.0 and setup an updateAsync and it worked as expected without any errors. I’m assuming the issue is something else that is in our larger applications but I’m at a loss for right now.