Im so frustrated. Avoid duplicated nested objects within the same document ONLY

Hello Everybody i’m so sorry to ask but i’ve been trying to look for an answer for MONTHS, and im already desperate because i can’t seem to find what i need till the point that i’m almost giving up with NoSQL.

So here’s my Schema.
I have States of a Country and they have their non-repeatable ISO CODE,

{
code: 'US-NY',
name: 'New York',
cities: [ ]
},
etc ..

… however inside the state (nested objects) we have cities:

cities:[
     {
           code: 'new-york',
           name:'New York',
     },
     {
           code: 'bufalo',
           name:'Búfalo',
     },
]

So when i add a document, i want to avoid duplicated nested objects (cities) with the same code (example: ‘bufalo’) within the same document (state).
BUT i could use ‘bufalo’ in another document (state).

When i set an index to cities.code to be Unique, it applies in the whole collection, and i want to use that code in another document.
I would like to repeat ‘bufalo’ city code in another document (state), but i dont want it to be repeated in the same document.

How could i archive this? Thank you so much for your kind help, i will be checking this post desperately.

Thanks

Alan D.

Hi @AlanDanielx_N_A,

When i set an index to cities.code to be Unique , it applies in the whole collection, and i want to use that code in another document.

I’d like to clarify that currently indexes work on the collection level so this behaviour is expected. The reason being is that indexes are used to select documents to return (as a subset of the collection) so this will not work inside a single document.

So when i add a document , i want to avoid duplicated nested objects (cities) with the same code (example: ‘bufalo’) within the same document (state).
BUT i could use ‘bufalo’ in another document (state).

Looking at the "cities" array field, perhaps utilising $addToSet may suit your use case. As per the $addToSet documentation:

The $addToSet operator adds a value to an array unless the value is already present, in which case $addToSet does nothing to that array.

Regards,
Jason

4 Likes

What I’ve done once, is dropping array for subobject instead. So instead of

{
  code: 'US-NY',
  name: 'New York',
  cities: [
     {
           code: 'new-york',
           name:'New York',
     },
     {
           code: 'bufalo',
           name:'Búfalo',
     } ]
}

you get

  code: 'US-NY',
  name: 'New York',
  cities: 
     {
        'new-york': {           
           code: 'new-york',
           name:'New York',
       },
       'bufalo': {
           code: 'bufalo',
           name:'Búfalo',
       } 
   }
}

this of cause change the way you can work with the document, but it might suit your need. Or it might not. It depends :wink:

Anyway - there are some nice operators that can help you out if you change the schema.
Like the aggregation operator $objectToArray that can convert the object back into an array.
And checking if a city exist becomes super simple with the $exists operator. Deleting with the $unset operator etc.

But again - you might have other criteria’s that demands an array.

2 Likes