Search code examples
javascriptnode.jsmongodbmongoose

how to search in compound indexed document with partial part of the index in Mongoose


Hi i have a schema with composed index to keep a unique combinaison of mail and organisation in my MongoDB like this

let Schema = mongoose.Schema({
    _id:{
        organisation:{
            type:mongoose.ObjectId,
            required:true
            ref:'organisations'
        },
        mail:{
            type:String,
            required:true
        }
    },
    firstName:{ 
        type:String,
    },
    lastName:{
        type:String
    },
})
//some methods and statics here

const Contact = mongoose.model('contacts',Schema);

I would like to query all documents that match a specific organisation id without giving a mail ( for listing from organisation purpose ) I have read something about this

await Contact
   .find(
      {
         _id:{
            organisation:organisation,
            mail:{"$exists":true}
         }
      }
   )

but i get an empty result so I try some regex

await Contact
   .find(
      {
         _id:{
            organisation:organisation,
            mail:{"$regex":"[^]*"}
         }
      }
   )

but i keep getting the same empty result the only time I get result is when precising the exact mail of a document but its useless for listing all the mail of an organisation

Does anyone know what am i doing wrong ? sorry i am kinda new at this NodeJS > Mongoose > MongoDB Stack


Solution

  • The problem being encountered here is related to the semantics when a full nested document is specified in the query. Per the documentation:

    Equality matches on the whole embedded document require an exact match of the specified <value> document, including the field order.

    So the first query in the question is looking for a document whose _id value is exactly { organisation:organisation, mail:{"$exists":true} } (with whatever value is present for the organisation variable at the time). I had to use a different field name due to a restriction with the $ in subfields of _id, but you can see a general example of the problem and semantics in this playground demo.

    What you want instead is to use dot notation.Specifically something like:

    db.collection.find({
      "_id.organisation": 123,
      "_id.mail": {
        "$exists": true
      }
    })
    

    See the playground demonstration here.