15
arr=[{field1:<value1>,field2:<value2}.....]

I want to use the $in operator against the field1 of arr. I know I could create a dummy array and push the field1 values in the dummy array. But is there a way to use the $in operator against a particular field of an array?

The arr array is no way related to the collection.

I want to query all the documents on a particular field whose value is in the field1 of arr - field1 should be in the right hand side of operator $in

Example:

arr=[{name:'foo',location:'NY'},{name:'bar',location:'LA'},{name:'foobar',location:'NZ'}]

db.collection.find({fieldx:<Here I want some method to obtain all documents whose fieldx values are in the location field of arr>})

The output should contain documents whose fieldx values are present in the location field of arr.

The ouput of the query should be

[{... 
    fieldx:'NY',
...
},
{...
    fieldx:'LA',
...
},
{...
    fieldx:'NZ',
...
}]

fieldx is the field in the collection I am querying on. It is not a field of the array I'm providing(arr). I want to match this to a field(location) of array - arr I'm providing the query.

6
  • Just to clear up your comments, you basically want to do ` "array": [{ "field1": { "$in": <values> }},{ "field2": { "$in": <values> } }]` in some form of valid syntax right? And does that mean that both "field1" and "field2" must much or does it mean either of them? Commented Jul 1, 2014 at 10:33
  • I am not sure what you are implying. I want to do a query on a field similar to $in. But as $in operator compares the whole objects in the given array, I want to match a single field on the array given on the right hand side of $in. Basically my primary need is to use dot notation on the right hand side of in(on the array given to query) Commented Jul 1, 2014 at 10:38
  • The example goes some way, clarification is what people are looking for. So "fieldx" is another field in the document and you want to know if that matches something in an array you provide? Or is that another array field in the document? Again, edits are better. Just tell people when you have made the changes. And "tag" using @username Commented Jul 1, 2014 at 10:46
  • @NeilLunn fieldx is the only field in the document I'm worried about. arr has no connection to the collection. I don't want to extract the specific field values in arr into a new array and do $in query on fieldx against the new array. Is there a more direct way? Commented Jul 1, 2014 at 10:48
  • Please read back. You are not explaining yourself properly, which is why you do not have an answer yet. My last comment was very specific. You have something to address. Commented Jul 1, 2014 at 10:50

3 Answers 3

16

You need to extract the "location" fields from your input array and feed them to $in:

var locs = arr.map(function(x) { return x.location } );
db.collection.find({ "fieldx": { "$in": locs } })

For reference here I'm going to re-write your question for you:

I have a collection that contains documents like this:

{ "fieldx": "NY" }
{ "fieldx": "LA" }
{ "fieldx": "SF" }

What I have is an input array that is defined like this:

var arr = [
    { "name": "foo", "location": "NY"},
    { "name": "bar", "location": "LA"},
    { "name": "foobar", "location": "NZ"}
];

Now I want to write a query to find all the documents that match the "location" field in the array I have for input.

How do I do I do that?

I have tried:

db.collection.find({ "fieldx": { "$in": arr } })

But that does not match.

Sign up to request clarification or add additional context in comments.

Comments

2

Extending Neil Lunn's answers, you can use map function within query also.

var arr = [
    { "name": "foo", "location": "NY"},
    { "name": "bar", "location": "LA"},
    { "name": "foobar", "location": "NZ"}
];

db.collection.find({ "fieldx": { "$in": arr.map(function(x) { return x.location } ) } })

If you using ES6 syntax then

db.collection.find({ "fieldx": { "$in": arr.map(x => x.location ) } })

Comments

1

You need to use dot notation to select fields in the array:

db.coll.find({"arr.field1" : { $in : [ 'value1', 'value11' ]}});

This query will return all documents where array arr contains at least one subdocument that has a field field1 with values value1 or value11.

Edit

Regarding your edit, you can't use $in operator that way.

From the documentation:

The $in operator selects the documents where the value of a field equals any value in the specified array.

If you send an array of objects in the $in query it will match document where specified field contains that object:

db.coll.find({ a: { $in : [ { b : 1, c: 1}, { b : 2, c: 2}  ]}});

Will find this documents:

{ 
    _id : ...
    a: { b : 1, c: 1} 
}
{ 
    _id : ...
    a: { b : 2, c: 2} 
}

To get what you really want, easiest way to query is to extract the values from your array of objects and do a query with the created array of values.

4 Comments

I want to use the field1 for the right hand side of the operator $in. I am sorry if the question wasn't clear enough
Again I don't think you understood my question correctly. Maybe I didn't put it right. I have a field - queryfield in the collection. I have an array which is not related to the collection - array1 which has objects in it. I want to query on the queryfield against a particular field of array1. The array is not in the document.
I wanted to avoid extracting the values to a new array and see if there's any method for the desired query. So there's no other way(using '$in' or not) to do this more efficiently?
@ma08 extracting values and using $in operator will be the most simple and efficient way to do your query.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.