Simpleschema gives error when Mongo update array of objects: Why does update a field in in array over all documents not work?


#1

Hi

do you maybe see whats wrong with this simple query?
I already looked here

Meteor.methods({
    resetLoggedInUser() {
        console.log("Method resetLoggedInUsers");
        //https://docs.mongodb.com/manual/tutorial/update-documents/#update-multiple-documents
        Customers.update({}, {
            $set: { "users.$.currentlyLoggedIn": false }
        });

my Customer schema


export const Customers = new Mongo.Collection('customers');

Customers.attachSchema(new SimpleSchema({
    name: {
        type: String,
        label: "Name of your customer"
    },
    checked: {
        type: Boolean,
        label: "Selected for the generation?",
        optional: true
    },
    createdAt: {
        type: Date,
        label: "Date created",
        optional: true
    },
    createdBy: {
        type: Object,
        label: "Date created",
        optional: true
    },
    users: {
        type: Array,
        optional: true
    },
    "users.$": {
        type: Object
    },
    "users.$.name": {
        type: String
    },
    "users.$.group": {
        type: String
    },
    "users.$.currentlyLoggedIn": {
        type: Boolean
    },
    "users.$.country": {
        type: String
    }
}));

the error I get:

Thank you


#2

I’m not sure if that’s exactly your schema, or if you’re just normalizing your schema with “$” for the purposes of showing us. But if your field names really do include ".$"…

Do not use ".$" in your field names!!! This is reserved for MongoDB and is used to refer to elements in an array field which were matched in the query selector.


#3

Thank you.

That is the Validation schema for the collection. https://github.com/aldeed/meteor-simple-schema

The field in mongo looks like
`users.currentlyLoggedin’


#4

Mm, maybe this works http://maz-dev.cc/update-on-mongo-subdocuments/


#5

There is no type: Array (rules), do you maybe want this:

users: {
  type: [Object],
  optional: true
},

#6

@hoser23331, Simple Schema hasn’t got any rule called Array, so use [Object] instead as @mitjajez rightfully suggested.


#7

Funny, I see what you mean in simpleschema. But I generated my code with this tool, so is that a bug?
http://autoform.meteorapp.com/quickform

Btw, it did not solve the issue, I still get

MongoError: The positional operator did not find the match needed from the query. Unexpanded update: users.$.currentlyLoggedIn

#8

I suspect the issue comes from simpleschema. It tries to validate my update. That is ok. But I want to update all documents, So I leave the query param empty {}.

I also tried this solution (did not work)

 Customers.update({
        }, {
            $set: {
                'users.$': {
                    'currentlyLoggedIn': false
                }
            }
        });
        // Customers.update({}, {

#9

I think the issue is, is that the update statement removes the whole object and therefore the validation fails. I just want to say: for all my document for all users set logged in to false.


#10

I think you’re correct, it removes all just what you update: {} = all.
If you want to update specific field vallue/document, you should specify it, try:

Customers.update(
  { users: "Who" },
  { $set: "users.$.currentlyLoggedIn": false }
)

#11

Ok thank you. But I want to update all users. So I don’t know the WHO, therefore I keep the query empty…Can this be done?


#12

yeah @hoser23331 … just use {} instead of {user: "Who"} in the query. so it’s going to be like this:

Customers.update({}, {$set: "users.$.currentlyLoggedIn": false })

#13

Hi,
@snamoah , thanks but that does not work as mentoined above.

I now have this working, but please tell me we can do it smarter in meteor…

Meteor.methods({
    resetLoggedInUser() {
        console.log("Method resetLoggedInUsers");

        Customers.find()
            .forEach(function(customer) {
                var updatedUsers = _.map(customer.users, function(user) {
                    user.currentlyLoggedIn = false;
                    return user;
                })

                Customers.update(customer._id, {
                    $set: { users: updatedUsers },
                });
            })

#14

That’s strange @hoser23331 because according to the mongodb doc, that’s how to get it to work.

Aah… actually I think I know what the problem is. It was my mistake. I mixed coffeescript with the javascript. Here’s the correct code:

Customers.update({}, {$set: {"users.$.currentlyLoggedIn": false}});

I hope it helps


#15

Thank you! because I hate my correct code, way to long!