I would like to save a single document into a variable in Mongo JS shell, and manipulate the document (read/write several attributes) for latter operations, but Mongo JS does not seem to put anything into the variable:
> a = db.col.find().limit(1)
{ "_id" : ObjectId("52dfccba5fd17fe6a4d0051a"), "a" : 16807, "b" : 475249 }
> a
>
Does mongo support the usage? Or was there a mistake?
You need to use var
like so:
> var a = db.col.find().limit(1)
{ "_id" : ObjectId("52dfccba5fd17fe6a4d0051a"), "a" : 16807, "b" : 475249 }
> a
{ "_id" : ObjectId("52dfccba5fd17fe6a4d0051a"), "a" : 16807, "b" : 475249 }
Doing some testing I have noticed that the find()
method does appear to be setting the variable to a cursor. In these cases, you lose the variable after the next statement.
> var a = db.col.find().limit(1)
{ "_id" : ObjectId("52dfccba5fd17fe6a4d0051a"), "a" : 16807, "b" : 475249 }
> var b = 'test'
> a
>
If you need to keep the variable around for longer, try explicitly iterating the variable before setting it using toArray()
.
> var a = db.col.find().limit(1).toArray()
{ "_id" : ObjectId("52dfccba5fd17fe6a4d0051a"), "a" : 16807, "b" : 475249 }
> var b = 'test'
> a
[
{
"_id" : ObjectId("52dfccba5fd17fe6a4d0051a"),
"a" : 16807,
"b" : 475249
}
]
find returns a cursor. A cursor can only be enumerated once, so once you've enumerated a cursor it has reached the end and will yield no further documents. So in the following example the variable a is assigned a cursor value, and the first time we evaluate "a" in the shell it echoes the results of enumerating the cursor. The second time we evalute "a" it enumerates the cursor again, but this time the cursor is empty so no documents are echoed:
> var a = db.test.find().limit(1)
> a
{ "_id" : ObjectId("52dfccba5fd17fe6a4d0051a"), "a" : 16807, "b" : 475249 }
> a
>
The previous example returns a cursor even though you used limit(1). It's not that "a" loses its value, it still refers to the same cursor, it's just that the cursor it refers to has reached its end.
If you want to read a single document and have the return value be a document instead of a cursor use findOne:
> var a = db.test.findOne()
> a
{ "_id" : ObjectId("52dfccba5fd17fe6a4d0051a"), "a" : 16807, "b" : 475249 }
> a
{ "_id" : ObjectId("52dfccba5fd17fe6a4d0051a"), "a" : 16807, "b" : 475249 }
>
If you want only one element and want to avoid the "lose the variable" problem described in another answers you can use findOne()
instead of find()
:
> var doc = db.col.findOne()
The doc
variable set in that way will be permanent.
If you are using aggregate
or find
to query, you had better use var
:
var result = db.mycollector.find()
print(result._batch[0]) // get first element