mongodb length of a property - mongodb

Documents present in my collection,
"info"{name : "sample"}, "extraInfo"{ tempCode :"1020200", newCode :"3844"}
I want to get all the documents having the newCode length > 3. I have tried below way,db.collection.find({$where:"this.extraInfo.newCode.length > 3"})
which returns result as
{
"code" : 16722
}

use {$exists:true} in order to get it right
db.collection.find({"newCode" : {$exists:true}, $where:"this.extraInfo.newCode.length > 3"})

Related

Mongo query with sort inner field returns lesser results than in the collection

Mongodb contains a collection that has following objects,
Objects with lastTrip :
{
"usage" : 0,
"lastMaintenanceDate" : NumberLong(1572600811104),
"lastTrip" : {
"direction" : "DOWN",
"startLevel" : 5
}
}
Objects without lastTrip:
{
"usage" : 0,
"lastMaintenanceDate" : NumberLong(1572600811104),
}
And following query is used to retrieve data with sorting,
Query one:
db.getCollection('some_collection').find({}).sort({"lastTrip.startLevel":1})
This only returns objects with the field lastTrip, even though collection contains objects without that field.
This issue is causing me getting wrong count on following query,
Query two:
db.getCollection('some_collection').find({}).sort({"lastTrip.startLevel":1}).count()
Expected result:
Query one > 20 documents
Query two > 20
Actual result:
Query one > 15 documents
Query two > 20
What is the proper way of querying(for query one) to get objects without the field lastTrip as well?

MongoDB get object id by finding on another column value

I am new to querying dbs and especially mongodb.If I run :
db.<customers>.find({"contact_name: Anny Hatte"})
I get:
{
"_id" : ObjectId("55f7076079cebe83d0b3cffd"),
"company_name" : "Gap",
"contact_name" : "Anny Hatte",
"email" : "ahatte#gmail.com"
}
I wish to get the value of the "_id" attribute from this query result. How do I achieve that?
Similarly, if I have another collection, named items, with the following data:
{
"_id" : ObjectId("55f7076079cebe83d0b3d009"),
"_customer" : ObjectId("55f7076079cebe83d0b3cfda"),
"school" : "St. Patrick's"
}
Here, the "_customer" field is the "_id" of the customer collection (the previous collection). I wish to get the "_id", the "_customer" and the "school" field values for the record where "_customer" of items-collection equals "_id" of customers-collection.
How do I go about this?
I wish to get the value of the "_id" attribute from this query result.
How do I achieve that?
The find() method returns a cursor to the results, which you can iterate and retrieve the documents in the result set. You can do this using forEach().
var cursor = db.customers.find({"contact_name: Anny Hatte"});
cursor.forEach(function(customer){
//access all the attributes of the document here
var id = customer._id;
})
You could make use of the aggregation pipeline's $lookup stage that has been introduced as part of 3.2, to look up and fetch the matching rows in some other related collection.
db.customers.aggregate([
{$match:{"contact_name":"Anny Hatte"}},
{$lookup:{
"from":"items",
"localField":"_id",
"foreignField":"_customer",
"as":"items"
}}
])
In case you are using a previous version of mongodb where the stage is not supported, then, you would need to fire an extra query to lookup the items collection, for each customer.
db.customers.find(
{"contact_name":"Anny Hatte"}).map(function(customer){
customer["items"] = [];
db.items.find({"_customer":customer._id}).forEach(function(item){
customer.items.push(item);
})
return customer;
})

Using $where to compare against nested field

I have a mongodb collection with documents of the following structure (simplifying it, the numbers are just for example):
{'a' : 1, 'b' : {'c':2}}
I want to run the following mongodb query:
{'$where' : 'this.a < this.b.c'}
The above doesn't work.
What is the correct syntax for such a query ?
Found the issue: not all of my collection documents contained the "b" value, and thus I was receiving an error:
db.alerts.find({$where:"this.a < this.b.c"})
error: {
"$err" : "TypeError: Cannot read property 'c' of undefined",
"code" : 16722
}
Fixed by changing my query to:
{"b.c":{$exists : true}, $where : "this.c < this.b.c"}

MongoDB: Adding a new field based on an existing field using $substr

I have a simple collection like below
> db.test.save({first:"Ab"})
> db.test.find()
{ "_id" : ObjectId("518a1524f635dc8bb092e1ac"), "first" : "Ab" }
I want to add a new field called 'fl' which holds the first letter of the field "first".
I tried this
> db.test.update({},{"$set":{"fl":{"$substr":["$first",0,1]}}})
not okForStorage
But I get the exception "not okForStorage" as you can see.
Any suggestions, workarounds?
Possibly a duplicate of Multiply field by value in Mongodb but here's a workaround:
db.test.find().forEach(function(e) {
e.fi = e.first[0];
db.save(e);
});

Get position of selected document in collection [mongoDB]

How to get position (index) of selected document in mongo collection?
E.g.
this document: db.myCollection.find({"id":12345})
has index 3 in myCollection
myCollection:
id: 12340, name: 'G'
id: 12343, name: 'V'
id: 12345, name: 'A'
id: 12348, name: 'N'
If your requirement is to find the position of the document irrespective of any order, that is not
possible as MongoDb does not store the documents in specific order.
However,if you want to know the index based on some field, say _id , you can use this method.
If you are strictly following auto increments in your _id field. You can count all the documents
that have value less than that _id, say n , then n + 1 would be index of the document based on _id.
n = db.myCollection.find({"id": { "$lt" : 12345}}).count() ;
This would also be valid if documents are deleted from the collection.
As far as I know, there is no single command to do this, and this is impossible in general case (see Derick's answer). However, using count() for a query done on an ordered id value field seems to work. Warning: this assumes that there is a reliably ordered field, which is difficult to achieve in a concurrent writer case. In this example _id is used, however this will only work with a single writer case.:
MongoDB shell version: 2.0.1
connecting to: test
> use so_test
switched to db so_test
> db.example.insert({name: 'A'})
> db.example.insert({name: 'B'})
> db.example.insert({name: 'C'})
> db.example.insert({name: 'D'})
> db.example.insert({name: 'E'})
> db.example.insert({name: 'F'})
> db.example.find()
{ "_id" : ObjectId("4fc5f040fb359c680edf1a7b"), "name" : "A" }
{ "_id" : ObjectId("4fc5f046fb359c680edf1a7c"), "name" : "B" }
{ "_id" : ObjectId("4fc5f04afb359c680edf1a7d"), "name" : "C" }
{ "_id" : ObjectId("4fc5f04dfb359c680edf1a7e"), "name" : "D" }
{ "_id" : ObjectId("4fc5f050fb359c680edf1a7f"), "name" : "E" }
{ "_id" : ObjectId("4fc5f053fb359c680edf1a80"), "name" : "F" }
> db.example.find({_id: ObjectId("4fc5f050fb359c680edf1a7f")})
{ "_id" : ObjectId("4fc5f050fb359c680edf1a7f"), "name" : "E" }
> db.example.find({_id: {$lte: ObjectId("4fc5f050fb359c680edf1a7f")}}).count()
5
>
This should also be fairly fast if the queried field is indexed. The example is in mongo shell, but count() should be available in all driver libs as well.
This might be very slow but straightforward method. Here you can pass as usual query. Just I am looping all the documents and checking if condition to match the record. Here I am checking with _id field. You can use any other single field or multiple fields to check it.
var docIndex = 0;
db.url_list.find({},{"_id":1}).forEach(function(doc){
docIndex++;
if("5801ed58a8242ba30e8b46fa"==doc["_id"]){
print('document position is...' + docIndex);
return false;
}
});
There is no way that MongoDB can return this as it does not keep documents in order in the database, just like MySQL f.e. doesn't name row numbers.
The ObjectID trick from jhonkola will only work if only one client creates new elements, as the ObjectIDs are generated on the client side, with the first part being a timestamp. There is no guaranteed order if different clients talk to the same server. Still, I would not rely on this.
I also don't quite understand what you are trying to do though, so perhaps mention that in your question? I can then update the answer.
Restructure your collection to include the position of any entry i.e {'id': 12340, 'name': 'G', 'position': 1} then when searching the database collection(myCollection) using the desired position as a query
The queries I use that return the entire collection all use sort to get a reproducible order, find.sort.forEach works with the script above to get the correct index.