How to query an array of objects to match any of the provided values?

Hey guys, so in my schema i have an array of objects, it looks like this:

entries: [
  {
    name: 'frank',
    age: 15,
    email: 'frank@email.com'
  },
{
    name: 'daniel',
    age: 18,
    email: 'daniel@email.com'
  }
]

So, what I need is: I want to query through this array of objects and check if it will match any of the values I provided. For example, lets suppose I have a name and a email - I need to build a query providing the name and the email and check if, in this array, the name or the email already exists.

But, I don’t want to query for exact match, i mean, i want to check if the email or the name already exists there, but both could be in separated objects.

On the example I provided, lets suppose I have the name frank and the email daniel@email.com and I make a query with both - both already exists so i do something with that…

The purpose is to avoid duplicated entries for example.

Hi,

You can do it like this:

db.collection.find({
  "entries.name": "frank",
  "entries.email": "daniel@email.com"
})

Working example

Ah cool, didnt think it was so easy. Thank you

What about if I need to put the id of the collection? Like findOne by id and search on the entries array of objects

Hi,

Can you give an example and expected output?

I have a collection with the entries array of objects (name, email, age). I want to build a query where I provide some values, like age and email for example. It will retrieve any array of object that contains name or the mail or the age provided.

For example, if I want to query for email, i would do like that:

db.collection.findOne({_id, "entries.name": name});

If you specify _id in your query, there is no point in specifying anything else because _id is unique.

You didnt get it. I have the id of the collection where the array is located at.

collection

  • array of objects

I have th id of the collection and i need to find any match inside the array of objects, to avoid duplicates.

Indeed. I do not get it. The statement

asked to findOne document from the collection named collection, because you do db.collection.findOne. And you want the document to match the query { _id , “entries.name” : name }.

The _id in the above is not

The _id in the above is the unique _id of one and only one document in the collection named collection. So what specifying entries.name can do in your query is to prevent you from find the document with the given _id.

yea, sorry, exactly, the id of the document that contains the entries inside. Look the query you wrote, thats right, but what if instead of just name i want to query for email and name? like two arguments?

@NeNaD has already provided the solution for that.

But this query would be querying all the documents. I want to query only one specific document (which I have the id). The array of objects is inside this document

Yes it will

Now it makes more sense than

So the answer should make more sense too.

Documents in collection

{ "_id" : 0 ,
  "entries" :  [
    { "name" : 2 , "age" : 3 } ,
    { "name" : 4 , "age" : 5 } ,
    { "name" : 6 , "age" : 7 }
  ]
} 

{ "_id" : 1 ,
  "entries" :  [
    { "name" : 2 , "age" : 5 } ,
    { "name" : 4 , "age" : 3 }
  ]
}

The following query will find all documents.

{ "entries.name" : 2 , "entries.age" : 3 }

However this one, will only find _id:0 because it is specified in the query.

{ "_id" : 0 , "entries.name" : 2 , "entries.age" : 3 }

The next one will only find _id:0. It does not find _id:1 because name:2 and age:3 is not both true for the same element.

{ "entries" : { "$elemMatch" : { "name" : 2 , "age" : 3 } }

In all cases, all elements of entries are sent in the result. To restrict the element of entries that are sent you need to use

or

I think both only project the first element that matches. The only way I know to project more element will be to use $filter within an aggregation pipeline.

This topic was automatically closed 5 days after the last reply. New replies are no longer allowed.