Tuesday, February 16, 2016

MongoDB - Mastering Find Command

You can use the find() method to issue a query to retrieve data from a collection in MongoDB. All queries in MongoDB have the scope of a single collection.
Queries can return all documents in a collection or only the documents that match a specified filter or criteria. You can specify the filter or criteria in a document and pass as a parameter to the find() method.
The find() method returns query results in a cursor, which is an iterable object that yields documents.
Field Selection

db.collection.find(queryprojection)
Selects documents in a collection and returns a cursor to the selected documents. 
ParameterTypeDescription
querydocumentOptional. Specifies selection criteria using query operators. To return all documents in a collection, omit this parameter or pass an empty document ({}).
projectiondocumentOptional. Specifies the fields to return using projection operators. To return all fields in the matching document, omit this parameter.
Returns:A cursor to the documents that match the query criteria. When the find() method “returns documents,” the method is actually returning a cursor to the documents.

Before we jump into cursors, you should know that find takes a second optional parameter called “projection”. This parameter is the list of fields we want to retrieve or exclude. 

The projection parameter takes a document of the following form:
{ field1: <boolean>, field2: <boolean> ... }
The <boolean> value can be any of the following:
  • 1 or true to include the field. The find() method always includes the _id field even if the field is not explicitly stated to return in the projection parameter.
  • 0 or false to exclude the field.
By default, the _id field is always returned. We can explicitly exclude it by specifying {name:1, _id: 0}.
Aside from the _id field, you cannot mix and match inclusion and exclusion. If you think about it, that actually makes sense. You either want to select or exclude one or more fields explicitly.  A projection cannot contain both include and exclude specifications, except for the exclusion of the _id field. In projections that explicitly include fields, the _id field is the only field that you can explicitly exclude.

For example, we can get all of the unicorns’ names without getting back other fields by executing:
db.unicorns.find({}, {name: 1});
> db.unicorns.find({},{name:1}).pretty()
{ "_id" : ObjectId("56bf377510a4febbd2830cfc"), "name" : "Horny" }
{ "_id" : ObjectId("56bf377510a4febbd2830cfd"), "name" : "Aurora" }
{ "_id" : ObjectId("56bf377510a4febbd2830cfe"), "name" : "Unicrom" }
{ "_id" : ObjectId("56bf377510a4febbd2830cff"), "name" : "Roooooodles" }
{ "_id" : ObjectId("56bf377710a4febbd2830d00"), "name" : "Solnara" }

> db.unicorns.find({},{name:1, _id:0}).pretty()
{ "name" : "Horny" }
{ "name" : "Aurora" }
{ "name" : "Unicrom" }
{ "name" : "Roooooodles" }
{ "name" : "Solnara" }

> db.unicorns.find({},{name:1, gender:1, _id:0}).pretty()
{ "name" : "Horny", "gender" : "m" }
{ "name" : "Aurora", "gender" : "f" }
{ "name" : "Unicrom", "gender" : "m" }
{ "name" : "Roooooodles", "gender" : "m" }
{ "name" : "Solnara", "gender" : "f" }

> db.unicorns.find({},{_id:0,loves:0,gender:0, dob:0}).pretty()
{ "name" : "Horny", "weight" : 600, "vampires" : 63 }
{ "name" : "Aurora", "weight" : 450, "vampires" : 41 }
{ "name" : "Unicrom", "weight" : 988.6799999999998, "vampires" : 182 }
{ "weight" : 600, "name" : "Roooooodles", "vampires" : 99 }
{ "name" : "Solnara", "weight" : 550, "vampires" : 80 }

There’s more to find than understanding selectors though. We already mentioned that the result from find is a cursor. We’ll now look at exactly what this means in more detail.

Explicitly Excluded Fields

The following operation queries the bios collection and returns all fields except the first field in the nameembedded document and the birth field:
db.bios.find(
   { contribs: 'OOP' },
   { 'name.first': 0, birth: 0 })

On Arrays and Embedded Documents

The following operation queries the bios collection and returns the last field in the name embedded document and the first two elements in the contribs array:
db.bios.find(
   { },
   {
     _id: 0,
     'name.last': 1,
     contribs: { $slice: 2 }
   }
)

Find All Documents in a Collection

The find() method with no parameters returns all documents from a collection and returns all fields for the documents. For example, the following operation returns all documents in the bios collection:
db.unicorns.find()

Find Documents that Match Query Criteria

To find documents that match a set of selection criteria, call find() with the <criteria> parameter. The following operation returns all the documents from the collection products where qty is greater than 25:
db.products.find( { qty: { $gt: 25 } } )
> db.unicorns.find({weight:{$gt:700}}).pretty()
{
        "_id" : ObjectId("56bf377510a4febbd2830cfe"),
        "name" : "Unicrom",
        "dob" : ISODate("1973-02-09T16:40:00Z"),
        "loves" : [
                "energon",
                "redbull"
        ],
        "weight" : 988.6799999999998,
        "gender" : "m",
        "vampires" : 182
}
{
        "_id" : ObjectId("56bf378810a4febbd2830d01"),
        "name" : "Ayna",
        "dob" : ISODate("1998-03-07T03:00:00Z"),
        "loves" : [
                "strawberry",
                "lemon"
        ],
        "weight" : 734.56,
        "gender" : "f",
        "vampires" : 40
}

Query for Equality

The following operation returns documents in the bios collection where _id equals 5:
db.bios.find( { _id: 5 } )

Query Using Operators

The following operation returns documents in the bios collection where _id equals either 5 orObjectId("507c35dd8fada716c89d0013"):
db.bios.find(
   {
      _id: { $in: [ 5,  ObjectId("507c35dd8fada716c89d0013") ] }
   }
)


Query for Ranges

Combine comparison operators to specify ranges. The following operation returns documents with fieldbetween value1 and value2:
db.collection.find( { field: { $gt: value1, $lt: value2 } } );

Combine Conditions

You can combine multiple query conditions in logical conjunction (AND) and logical disjunctions (OR).

Logical AND
You can specify a logical conjunction (AND) for a list of query conditions by separating the conditions with a comma in the conditions document.

db.restaurants.find( { "cuisine": "Italian", "address.zipcode": "10075" } )
The result set includes only the documents that matched all specified criteria.

Logical OR
You can specify a logical disjunction (OR) for a list of query conditions by using the $or query operator.

db.restaurants.find(
   { $or: [ { "cuisine": "Italian" }, { "address.zipcode": "10075" } ] }
)

Query a Field that Contains an Array

If a field contains an array and your query has multiple conditional operators, the field as a whole will match if either a single array element meets the conditions or a combination of array elements meet the conditions.
Given a collection students that contains the following documents:
{ "_id" : 1, "score" : [ -1, 3 ] }
{ "_id" : 2, "score" : [ 1, 5 ] }
{ "_id" : 3, "score" : [ 5, 5 ] }
The following query:
db.students.find( { score: { $gt: 0, $lt: 2 } } )
Matches the following documents:
{ "_id" : 1, "score" : [ -1, 3 ] }
{ "_id" : 2, "score" : [ 1, 5 ] }
In the document with _id equal to 1, the score: [ -1, 3 ] meets the conditions because the element-1 meets the $lt: 2 condition and the element 3 meets the $gt: 0 condition.
In the document with _id equal to 2, the score: [ 1, 5 ] meets the conditions because the element meets both the $lt: 2 condition and the $gt: 0 condition.

Query Arrays

Query for an Array Element

The following operation returns documents in the bios collection where the array field contribs contains the element "UNIX":
db.bios.find( { contribs: "UNIX" } )
> db.unicorns.find({loves:"watermelon"}).pretty()
{
        "_id" : ObjectId("56bf378810a4febbd2830d04"),
        "name" : "Leia",
        "dob" : ISODate("2001-10-08T09:23:00Z"),
        "loves" : [
                "apple",
                "watermelon"
        ],
        "weight" : 601,
        "gender" : "f",
        "vampires" : 33
}
{
        "_id" : ObjectId("56bf378810a4febbd2830d05"),
        "name" : "Pilot",
        "dob" : ISODate("1997-02-28T23:33:00Z"),
        "loves" : [
                "apple",
                "watermelon"
        ],
        "weight" : 650,
        "gender" : "m",
        "vampires" : 54
}
{
        "_id" : ObjectId("56bf378910a4febbd2830d07"),
        "name" : "Dunx",
        "dob" : ISODate("1976-07-18T12:48:00Z"),
        "loves" : [
                "grape",
                "watermelon"
        ],
        "weight" : 705.56,
        "gender" : "m",
        "vampires" : 165
}

Query an Array of Documents

The following operation returns documents in the bios collection where awards array contains an embedded document element that contains the award field equal to "Turing Award" and the year field greater than 1980:
db.bios.find(
   {
      awards: {
                $elemMatch: {
                     award: "Turing Award",
                     year: { $gt: 1980 }
                }
      }
   }
)
The name field must match the embedded document exactly. The query does not match documents with the following name fields:
{
   first: "Yukihiro",
   aka: "Matz",
   last: "Matsumoto"
}

{
   last: "Matsumoto",
   first: "Yukihiro"
}

Query Fields of an Embedded Document

The following operation returns documents in the bios collection where the embedded document name contains a field first with the value "Yukihiro" and a field last with the value "Matsumoto". The query uses dot notation to access fields in an embedded document:
The query matches the document where the name field contains an embedded document with the fieldfirst with the value "Yukihiro" and a field last with the value "Matsumoto". For instance, the query would match documents with name fields that held either of the following values:
{
  first: "Yukihiro",
  aka: "Matz",
  last: "Matsumoto"
}

{
  last: "Matsumoto",
  first: "Yukihiro"
}

Limit the Number of Documents to Return

The limit() method limits the number of documents in the result set. The following operation returns at most 5 documents in the bios collection:
db.bios.find().limit( 5 )
limit() corresponds to the LIMIT statement in SQL.

Set the Starting Point of the Result Set

The skip() method controls the starting point of the results set. The following operation skips the first 5documents in the bios collection and returns all remaining documents:
db.bios.find().skip( 5 )
Order Documents in the Result SetThe sort() method orders the documents in the result set. The following operation returns documents in the bios collection sorted in ascending order by the name field:
db.bios.find().sort( { name: 1 } )
sort() corresponds to the ORDER BY statement in SQL.
A few times now I’ve mentioned that find returns a cursor whose execution is delayed until needed. However, what you’ve no doubt observed from the shell is that find executes immediately. This is a behavior of the shell only. We can observe the true behavior of cursors by looking at one of the methods we can chain to find. The first that we’ll look at is sort. We specify the fields we want to sort on as a JSON document, using 1 for ascending and -1 for descending.

//heaviest unicorns first
db.unicorns.find().sort({weight: -1})
//by unicorn name then vampire kills:
db.unicorns.find().sort({name: 1, vampires: -1})

As with a relational database, MongoDB can use an index for sorting. We’ll look at indexes in more detail later on. However, you should know that MongoDB limits the size of your sort without an index. That is, if you try to sort a very large result set which can’t use an index, you’ll get an error.

Count

The shell makes it possible to execute a count directly on a collection, such as:
> db.unicorns.find().count()

12
> db.unicorns.count({vampires: {$gt: 50}})
6

In reality, count is actually a cursor method, the shell simply provides a shortcut. Drivers which don’t provide such a shortcut need to be executed like this (which will also work in the shell):
db.unicorns.find({vampires: {$gt: 50}}).count()

Paging

Paging results can be accomplished via the limit and skip cursor methods. To get the second and third heaviest unicorn, we could do:
db.unicorns.find()
.sort({weight: -1})
.limit(2)
.skip(1)
Using limit in conjunction with sort, can be a way to avoid running into problems when sorting on non-indexed fields.

2 comments:

  1. very informative blog and useful article thank you for sharing with us
    Big data hadoop online Course Bangalore

    ReplyDelete
  2. How to Solve MongoDB Database Creation Issue through DB Recovery Support
    Solve your MongoDB database creation issue with Cognegic’s most prominent support called DB Recovery Support or Exchange Recovery Support. Here our experts can easily optimize your physical, virtual and cloud-based MongoDB environment and make you error free. We use advance technique to solve your all problems and provides you effective solution within estimated time period.
    For More Info: https://cognegicsystems.com/
    Contact Number: 1-800-450-8670
    Email Address- info@cognegicsystems.com
    Company’s Address- 507 Copper Square Drive Bethel Connecticut (USA) 06801

    ReplyDelete

Mongodb explain() Query Analyzer and it's Verbosity

First creating 1 million documents: > for(i=0; i<100; i++) { for(j=0; j<100; j++) {x = []; for(k=0; k<100; k++) { x.push({a:...