Query for a field in an object in array with Mongo? - mongodb

Is it possible to use Mongo to query for entries that have a particular value in a field in an object in an array.
For example, let's say I want to find all objects where field1 has an array of objects, one of which has the field 'one' with a value of 1. This query should return the following object from my collection:
{_id: 0000, field1: [{one: 1, two: 2}, {one: 'uno', two: 'dos'}]}

I suppose what you need is:
db.collection.find( { field1: { $elemMatch: { one: 1 } } } );
http://docs.mongodb.org/manual/reference/operator/elemMatch/#op._S_elemMatch

This is an old question, but a simpler way to perform this query is to use dot notation:
db.collection.find({'field1.one': 1})

Related

How to fetch just the "_id" field from MongoDB find()

I wish to return just the document id's from mongo that match a find() query.
I know I can pass an object to exclude or include in the result set, however I cannot find a way to just return the _id field.
My thought process is returning just this bit of information is going to be way more efficient (my use case requires no other document data just the ObjectId).
An example query that I expected to work was:
collection.find({}, { _id: 1 }).toArray(function(err, docs) {
...
}
However this returns the entire document and not just the _id field.
You just need to use a projection to find what ya want.
collection.find({filter criteria here}, {foo: 0, bar: 0, _id: 1});
Since I don't know what your document collection looks like this is all I can do for you. foo: 0 for example is exclude this property.
I found that using the cursor object directly I can specify the required projection. The mongodb package on npm when calling toArray() is returning the entire document regardless of the projection specified in the initial find(). Fixed working example below that satisfies my requirements of just getting the _id field.
Example document:
{
_id: new ObjectId(...),
test1: "hello",
test2: "world!"
}
Working Projection
var cursor = collection.find({});
cursor.project({
test1: 0,
test2: 0
});
cursor.toArray(function(err, docs) {
// Importantly the docs objects here only
// have the field _id
});
Because _id is by definition unique, you can use distinct to get an array of the _id values of all documents as:
collection.distinct('_id', function(err, ids) {
...
}
you can do like this
collection.find({},'_id').toArray(function(err, docs) {
...
}

Query mongo document to return all rows in a field

For example, if I have a name field in mongo document person. In SQL, the query would be like select name from person; to return all names.
What is the equivalent in mongo?
I was thinking db.person.find(<<What do I fill here>>, {name: 1});
I was trying to retrieve all names while using mongo console.
An empty JSON object {} matches all documents.
db.person.find({}, {name: 1});
For correct syntaxe use best practices of mongoDB.
db.person.find(
{ },
{ name: 1, lastname: 1, _id: 0 }
)
In this exemple it shows only "name" and "lastname".

How to write MongoDB query statement for a specific requirement?

Here is the MongoDB document format:
{
'_id':...,
'user_id':...,
'user_info':...,
...
}
The user_info's value is a number or a string, I'd like to combine all the user_info's value into an array as the key 'user_info' 's value in the query result, like here:
{ 'user_id': ..., 'user_info': [ ..., ...] }
How to write the query statement to query data like this?
You need to use $in
The $in operator selects the documents where the value of a field equals any value in the specified array.
db.users.find({'user_info': {$in: [1, "a"]}})
Here you can read about it $in

mongodb find documents where all array values do NOT start with 'org:'

Given some documents like this:
{
_id: 'abc',
extIds: ['org1:123', 'org2:xyz', 'org3:7q9']
},
{
_id: 'def',
extIds: ['org1:234', 'org2:tuv']
}
I want to match those that don't have an extId value for 'org3'.
I tried a simple regex:
db.ext_ids.find({
extIds: {$regex:'^(?!org3\:)'}
})
But this matches all documents which have any extId value other than 'org3:...'.
Essentially, I need to evaluate the regex against all values in the array.
How about:
db.ext_ids.find({ extIds: {$not: /^org3/ }})

insert to specific index for mongo array

Mongo supports arrays of documents inside documents. For example, something like
{_id: 10, "coll": [1, 2, 3] }
Now, imagine I wanted to insert an arbitrary value at an arbitrary index
{_id: 10, "coll": [1, {name: 'new val'}, 2, 3] }
I know you can update values in place with $ and $set, but nothing for insertion. it kind of sucks to have to replace the entire array just for inserting at a specific index.
Starting with version 2.6 you finally can do this. You have to use $position operator. For your particular example:
db.students.update(
{ _id: 10},
{ $push: {
coll: {
$each: [ {name: 'new val'} ],
$position: 1
}
}}
)
The following will do the trick:
var insertPosition = 1;
var newItem = {name: 'new val'};
db.myCollection.find({_id: 10}).forEach(function(item)
{
item.coll = item.coll.slice(0, insertPosition).concat(newItem, item.coll.slice(insertPosition));
db.myCollection.save(item);
});
If the insertPosition is variable (i.e., you don't know exactly where you want to insert it, but you know you want to insert it after the item with name = "foo", just add a for() loop before the item.coll = assignment to find the insertPosition (and add 1 to it, since you want to insert it AFTER name = "foo".
Handy answer (not selected answer, but highest rated) from this similar post:
Can you have mongo $push prepend instead of append?
utilizes $set to insert 3 at the first position in an array, called "array". Sample from related answer by Sergey Nikitin:
db.test.update({"_id" : ObjectId("513ad0f8afdfe1e6736e49eb")},
{'$set': {'array.-1': 3}})
Regarding your comment:
Well.. with concurrent users this is going to be problematic with any database...
What I would do is the following:
Add a last modified timestamp to the document. Load the document, let the user modify it and use the timstamp as a filter when you update the document and also update the timestamp in one step. If it updates 0 documents you know it was modified in the meantime and you can ask the user to reload it.
Using the $position operator this can be done starting from version 2.5.3.
It must be used with the $each operator. From the documentation:
db.collection.update( <query>,
{ $push: {
<field>: {
$each: [ <value1>, <value2>, ... ],
$position: <num>
}
}
}
)