what is the meaning of first {} curly brace in mongodb projection query - mongodb

I want to know what is the need of first curly brace {} after find here in this query.
db.mycol.find({},{"title":1,_id:0})

It is an empty query, in the sense of a limiting boundary. So
db.mycol.find({},{"title":1,_id:0})
would basically translate to
Show me the title, but not the _id (as you would do by default) for all documents of the mycol collection in the current database.
Let's say you want all the titles written by Alan Turing. So you could modify the query part like this:
db.mycol.find({"author":"Alan Turing"},{"title":1,_id:0})
In general, MongoDB's find operation can be described like this
db.collection.find(query,projection)
For more detailed information, you might want to read find's documentation.

The first Curly braces is used as a where condition in MySql
Check out this Link - SQL to MongoDB Mapping Chart
MySQL
SELECT user_id, status FROM users WHERE status = "A"
MongoDB
db.users.find(
{ status: "A" },
{ user_id: 1, status: 1, _id: 0 }
)

This is called projection and tells which fields to show. For example here you show only title. It is something like Select title from mycol; If you will not specify projection it will return everything, which is close to select * from mycol;
_id is always shown, unless you hide it explicitly with _id: 0. Another thing is that you can not mix 0 and 1 (except for _id). But one more time - read FAQ.

You should refer this link for better explanation
http://docs.mongodb.org/manual/reference/operator/projection/positional/
first of all, projection does not return the first result it finds it tells mongo what to return.
.findOne(query) will LIMIT result to one or find(query).limit(1) will also do the same.
You say you are trying to "get all" your data.
a standard find type query will get your started...
find({mongo:query},{mongo:projection})
but limits results to a cursor from the mongo shell*

Related

Covered queries and find all (no filter)

I am not sure if it is possible, I'm just curious.
I have a region collection with the purpose of being loaded to a web dropdown. Not the big thing there.
{
_id:"some numeric id",
name:"region name",
}
and having the index created like db.regions.createIndex({name:1})
I tried both db.regions.find({},{_id:0}).sort(name:1) and without the sort.
Using the explain shows that the totalDocsExamined is greater than zero, so that means that it is not a covered query if I understood the concept.
For a covered query, you have to explicitly list each of the covered fields in the projection:
db.regions.find({}, {_id:0, name: 1}).sort({name:1})
If you only exclude _id, you're telling MongoDB to include all fields besides _id. You know that all your docs only have a name field, but MongoDB doesn't so you have to be explicit.

MongoDB returning latest documents from each category in one find statement?

Let's say I have a status and a createdAt field and a few other fields like title and content.
The status field can take on open, closed, or pending values.
I basically want to return the 5 latest documents from each status value in one find statement. Is this possible? Also, can this be done without aggregate?
If so, how?
Try following
db.collectionName.find().sort({"_id":-1}).limit(5).pretty()
It return's latest five documents
Bad news: that's not possible with basic queries. For a simple reason: you can only limit on a complete result set. So even when you use a logic OR on the status field, the first twenty documents of your result set may well all be of status "closed". When you apply whatever limit on this result set, up to the first twenty documents will have the status "closed".
I am not even sure wether this can be done easily with aggregation, I have to think about that.
Markus right. Unfortunatelly, it's not possible to do it in one aggregation query due to the lack of slice operation in a project phase of an aggregation pipeline.
It means, that you could easily group documents by status like this:
db.collectionName.aggregate([
{ "$group": {
"_id": "$status",
"docs": { "$push": "$title" }
}}
]);
BUT there is not way to slice resulting sub-arrays during this aggregation. This feature was requested, but not implemented yet.
You could slice it after aggregation using a separate command. Or you always have an option to use Map-Reduce.
Another option is to iterate over statuses in your application and query documents by each status. I would go with this solution in your scenario, because you have just 3 different statuses. It means only 3 queries. It is not fatal(especially if you have index on status field).

Mongodb select with condition is selected result must in sub select query

How do you do nested select in MongoDB analogous to
SELECT id FROM table1 WHERE id IN (SELECT id FROM table2)
MongoDB does not yet possess the ability to do subqueries which would allow this functionality.
I am sure it is something within the JIRA however, I could not immediately find it.
The only way currently is to actually pick the table, iterate the cursor pulling out the information and using that as part of a $in query as shown by #Bruno, like so:
ids=[];
for(i in db.c2.find({},{_id:1}){ // I have assumed id=_id
ids[ids.length]=i; // The default return of the index pos is actually _id
}
return db.c1.find({$in:ids});
As a mere example I wrote off of the top of my head.
This page contains comparator between SQL and MongoDB:
http://docs.mongodb.org/manual/reference/sql-comparison/
For example, you can to use a aggregation pipeline and where is the same as:
db.your_collection.aggregate({$match: {"id": {$in: ['id_0', 'id_1']} }})
A simple query as the same as:
db.your_collection.aggregate({field: "value"})
Mongodb official page has a lot of informations

Query without projection is not covered

See the shell example below (assumes db.test does not exist):
db.test.ensureIndex({info: 1, _id: 1})
db.test.insert({info: "info1"})
db.test.insert({info: "info2"})
db.test.insert({info: "info3"})
db.test.find({info: "info1"}).explain().indexOnly //is false
db.test.find({info: "info1"}, {_id: 1, info: 1}).explain().indexOnly //is true
The first explain has indexOnly : false whereas the second has indexOnly : true although the two queries are strictly equivalent.
Why isn't db.test.find({info: "info1"}) a covered query?
I have been thinking and testing this more and it does make sense now. If you add no projection MongoDB has no way of "knowing" if the index you have actually fills the entire return; I mean how can it know the index covers the projection without looking at the documents?
It is the same as select * and select d,e in SQL. How can you know that * is the same as d,e without actually looking?
If you supply a projection then MongoDB can "know" that looking at the index will give you your full result set however, without a projection it cannot.
So after some thinking I do not think this is a bug it is just a "quirk".

Mongo - dot notation works like $or? Can't provide multiple parameters?

I tried to update an existing document with two dot notation parameters, my query:
{ _id: "4eda5...", comments._id: "4eda6...", comments.author: "john" }
my update was:
{ "comments.$.deleted": true }
However, weirdly enough, when I passed a non-existent combination of comment id+author, it just updated the first matching comment by that author.
Any ideas why that's happening?
EDIT: C# Code sample
var query = Query.And(Query.EQ("_id", itemId), Query.EQ("cmts._id", commentId));
if (!string.IsNullOrEmpty(author))
query = Query.And(query, Query.EQ("cmts.Author", author));
var update = Update.Set("cmts.$.deleted", true);
var result = myCol.Update(query, update, UpdateFlags.None, SafeMode.True);
You want $elemMatch if you want the _id and author to be in the same comment. Really, your query doesn't make much sense including the author as the id should be as unique as you can get, no?
It is based on the first matching array element which replaces the "$" in for the update.
This is working by design. It is similar to an or since it can find a document which both has the _id and an author that match in any of the array elements.
The query is not working the way you are expecting it to. Basically, when using the $ positional notation you need to make sure that your query only has one clause that queries an array, otherwise it is ambiguous which of the two array comparisons the $ should refer to.
In your case, you are asking for a document where:
The _id is equal to some value
The comments array contains some document where the _id is equal to some value
The comments array contains some document where the author is equal to some value
Nothing in your query says that 2. and 3. need to be satisfied by the same document.
So even though you are using a non-existent combination of comment._id and comment.author, your comment array does have at least one entry where the _id is equal to your search value and some other entry (just not the same one) where the author is equal to your search value.
Since the author was the last one checked, that's what set the value of the $, and that's why that array element got updated.