How to update first empty object in array?

I’m also curious about the justification here. @kerbe, can you expand on why pre-allocation is necessary?

I highly recommend using supplementary fields instead. Having a field called currentNumberOfElements (or simply count) helps here. Instead of finding an empty object to update in an array of potentially one or more empty objects, I recommend using query predicates to decide if an update needs to occur or not.

For example:
{ arrayOfObjects: [ { a: 1, b: 1 } ], count: 1 }

The update statement can look like this:
db.collection.updateOne({ count: { $lt: 4 } }, { $push: { arrayOfObjects: { a: 2, b: 2 } }, $inc: { count: 1 } })

Only documents which have an “open” array position would be updated, removing the need to “find” an empty element. Does that work for your use case?

1 Like

It isn’t absolutely necessary, as I said before. It has felt convenient, and felt that it could reduce some queries and also some code in the way I have been doing it this far.

Maybe it wasn’t really clear in my original question, or hasn’t been clearly stated in later time, but I don’t try to find document which has empty object in array. Update is going to be for one specific document, which _id is known. So those examples @Justin gave, are unnecessary, or wouldn’t be used like that.

My document design comes from thought, that document has certain number of badges, which these objects represent. In application empty objects are rendered empty, and when they get content, they automatically render that content. I was thinking that I would have something like count, and first print outline, and then fill that with how many badges there is, but it felt unnecessary to store extra information to different field, and operate that, when structure of document itself already provides needed information.

I have also been thinking grouping these badges, and having extra variables for how they are wanted to be grouped felt really difficult. But thought now is that I can create multi dimensional array, which holds objects as they are planned to be rendered, and document structure itself then is used for rendering decisions.

And why it goes like that? Because there could be different layouts in documents. Some could be simple having 10 badges, that are dumbed as is. Others could have like 20 badges, but they are wanted to be grouped in four groups, each holding five badges. Or there could be document which has grouping where first row has only three badges, second one four, third one five… or something other funky groupings.

So, to get those funky groupings work, I came up that empty objects can show what is desired layout. At least currently it feels easier to start thinking how to render those, than having some other structure storing layout information.

And this query I was trying to figure out, was query to add one new badge to specific one document. I was thinking of just manipulating arrayOfObjects in nodejs code, and then push whole array replacing previous, but it felt wrong, as it would potentially change layout. So wanted to have update to target first empty object in that document, so structure remains always unaltered, and there shouldn’t potentially be race conditions if there would be multiple update operations directed to same document ~same time. This way update succees, if there is empty object, or should fail if there isn’t empty one anymore when MongoDB starts doing update (or well, not fail, but not update anything, which I can then detect in nodejs code, and work around that accordingly).

Of course, I am open for ideas, and curious to hear am I creating something that will shoot me in the leg in long run. Does my explanation give more insight of my design/thought process @Justin & @Robert_Cochran? Any comments or doubts?

@kerbe Thank you for the additional explanation. At this point, I do not have the context of your overall application, and the setting for your application. I have too little knowledge and definitely too little data. I might be able to say more if I saw a sample collection with about 20-100 documents in it that together fully represent your data structures and help illustrate the data that you have, and how you intend to update it.

I do not fully understand your use or business case. So I do not feel I can say much more than I have.

Best wishes to you!

Thanks so much


@kerbe, it sounds like you’ve got some very detailed use cases you’re trying to plan, which is great, but I recommend keeping your schema simple. A simple schema is logical and extendable. There may be some duplication or even a bit more compute required with a simple schema, but it’s a worthwhile trade-off.

Let’s look at badges. Here is my suggestion:
{ badges: [ { name: "Leafy" }, { name: "Rainbow" }, { name: "Party Parrot" } ] }

We have an array of documents. Why an array of documents instead of an array of strings? Extendability. Variability in your layout means changes could occur in the future. Using this type of schema allows for easy changes. Let’s say you want to allow users to group badges. That would look like this:
{ badges: [ { name: "Leafy", group: "MongoDB" }, { name: "Rainbow", group: "MongoDB" }, { name: "Party Parrot", group: "Animals" } ] }

Not only is it easy to add groups given a simple array of documents, but it gives your application much more power during development.

Does that help?


Well @Justin, I must say that no, that doesn’t help, you might have confused me quite much with your examples. :smiley:

Could you explain how is your example(s) different from what I described in starting post?

Or is it that I have confused you by talking about objects, and you talk about documents, and they seem to be same thing (at least notation seems same)? :slight_smile:

For most purposes, objects and documents are the same thing. Technically, object is a data type so an object is contained within a document.

I believe the examples do differ from what you described in the starting post. Taking a step back, do you have the information you need to resolve your problem?

Yes, I believe Asya’s example queries work and educated me about right syntax. :slight_smile: