How to access data from a nested array structured collection - mongodb

I have the following structure in my MongoDB .
I have a nested structure of my collection named chains which is shown below .
I am trying to access options of a particular date as shown below which is 2015-01-17 in my case .
db.chains.find({ "symbol" : "UBSC" ,"option_exp.expiration_dt" : "2015-01-17"}).pretty()
But the following query above is returning me all the data related to that Symbol .
{
"_id" : ObjectId("52000a90d293b0e4134e8c35"),
"symbol" : "UBSC",
"option_exp" : [
{
"expiration_dt" : "2015-01-17",
"options" : [
{
"mult" : "10"
},
{
"mult" : "10"
}
]
},
{
"expiration_dt" : "2014-01-18",
"options" : [
{
"prem_mult" : "10"
},
{
"prem_mult" : "10"
}
}
]
}
],
}
This is the way i was trying to access through java
BasicDBObject query = new BasicDBObject();
query.append("symbol", "UBSC");
query.append("option_exp.expiration_dt", "2015-01-17");
Could anybody please help me as how to access data of a particular date .

Use $elemMatch to limit content of option_exp array field that is included in result:
db.chains.find({symbol : "UBSC" ,"option_exp.expiration_dt" : "2015-01-17"},
{option_exp: {$elemMatch: {expiration_dt: "2015-01-17"}}})
This will select documents which have symbol equal to "UBSC" and option_exp array items with expiration_dt equal to "2015-01-17". Then we limit option_exp array content to items which have required expiration date (otherwise whole document will all option_exp items will be returned).

Related

MONGO - Know if all elements of input array is in mongoDB

I have a problem with mongo query. I have the next colecction.
"id" : "TEST"
"client" : "0048948",
"contracts" : [
{
"contractNumberId" : "contractNumber1",
"otherField" : "XXXXX",
"contractFormats" : [
{
"formatId" : "format12"
},
{
"formatId" : "format10"
}
]
},{
"contractNumberId" : "contractNumber2",
"otherField" : "XXXXX",
"contractFormats" : [
{
"formatId" : "format12"
},
{
"formatId" : "format15"
}
]
}
]
And I want to search if I have a collection in which I have all the values ​​of an array of contracts or formats that are passed to me. For example if in my input I have the next contracts or formats [contractNumber1, format15] My query should return true because I found it in my database, in contracts or format, but if for example mi inputs was [contractNumbe1, format50, contract3, 10], my query should return false, because any document of my database match that all ocurrences of the input is in any document.
The query should find in contracts and formats all inputs values of input array.
Can anyone help me please?. I have tried with $elemMatch, $nor and $in, $unwind but unsatisfactory result.
Thanks to all for your time.

How to query and get value from list in single document

I am trying to query a mongodb list in a single document. As shown below, I would like to match the code and get wheels value. if code = car then query should return wheels and allowed value for that list element. Below is a list from single document.
"vehicles" : [
{
"code" : "car",
"wheels":4,
"allowed": True
},
{
"code" : "Tuk Tuk",
"wheels":4
"allowed":True
},
{
"code" : "Bike",
"wheels":4
"allowed":False
}]
you can try like this
db.collectionName.find({"vehicles.code" : "car" }, {"vehicles.wheels" : 1 , "vehicles.allowed" : 1}).pretty()
here "vehicles.code" : "car" is the filter and "vehicles.wheels" : 1 will display the only wheels value and won't display any other fields

Resolving MongoDB DBRef array using Mongo Native Query and working on the resolved documents

My MongoDB collection is made up of 2 main collections :
1) Maps
{
"_id" : ObjectId("542489232436657966204394"),
"fileName" : "importFile1.json",
"territories" : [
{
"$ref" : "territories",
"$id" : ObjectId("5424892224366579662042e9")
},
{
"$ref" : "territories",
"$id" : ObjectId("5424892224366579662042ea")
}
]
},
{
"_id" : ObjectId("542489262436657966204398"),
"fileName" : "importFile2.json",
"territories" : [
{
"$ref" : "territories",
"$id" : ObjectId("542489232436657966204395")
}
],
"uploadDate" : ISODate("2012-08-22T09:06:40.000Z")
}
2) Territories, which are referenced in "Map" objects :
{
"_id" : ObjectId("5424892224366579662042e9"),
"name" : "Afghanistan",
"area" : 653958
},
{
"_id" : ObjectId("5424892224366579662042ea"),
"name" : "Angola",
"area" : 1252651
},
{
"_id" : ObjectId("542489232436657966204395"),
"name" : "Unknown",
"area" : 0
}
My objective is to list every map with their cumulative area and number of territories. I am trying the following query :
db.maps.aggregate(
{'$unwind':'$territories'},
{'$group':{
'_id':'$fileName',
'numberOf': {'$sum': '$territories.name'},
'locatedArea':{'$sum':'$territories.area'}
}
})
However the results show 0 for each of these values :
{
"result" : [
{
"_id" : "importFile2.json",
"numberOf" : 0,
"locatedArea" : 0
},
{
"_id" : "importFile1.json",
"numberOf" : 0,
"locatedArea" : 0
}
],
"ok" : 1
}
I probably did something wrong when trying to access to the member variables of Territory (name and area), but I couldn't find an example of such a case in the Mongo doc. area is stored as an integer, and name as a string.
I probably did something wrong when trying to access to the member variables of Territory (name and area), but I couldn't find an example
of such a case in the Mongo doc. area is stored as an integer, and
name as a string.
Yes indeed, the field "territories" has an array of database references and not the actual documents. DBRefs are objects that contain information with which we can locate the actual documents.
In the above example, you can clearly see this, fire the below mongo query:
db.maps.find({"_id":ObjectId("542489232436657966204394")}).forEach(function(do
c){print(doc.territories[0]);})
it will print the DBRef object rather than the document itself:
o/p: DBRef("territories", ObjectId("5424892224366579662042e9"))
so, '$sum': '$territories.name','$sum': '$territories.area' would show you '0' since there are no fields such as name or area.
So you need to resolve this reference to a document before doing something like $territories.name
To achieve what you want, you can make use of the map() function, since aggregation nor Map-reduce support sub queries, and you already have a self-contained map document, with references to its territories.
Steps to achieve:
a) get each map
b) resolve the `DBRef`.
c) calculate the total area, and the number of territories.
d) make and return the desired structure.
Mongo shell script:
db.maps.find().map(function(doc) {
var territory_refs = doc.territories.map(function(terr_ref) {
refName = terr_ref.$ref;
return terr_ref.$id;
});
var areaSum = 0;
db.refName.find({
"_id" : {
$in : territory_refs
}
}).forEach(function(i) {
areaSum += i.area;
});
return {
"id" : doc.fileName,
"noOfTerritories" : territory_refs.length,
"areaSum" : areaSum
};
})
o/p:
[
{
"id" : "importFile1.json",
"noOfTerritories" : 2,
"areaSum" : 1906609
},
{
"id" : "importFile2.json",
"noOfTerritories" : 1,
"areaSum" : 0
}
]
Map-Reduce functions should not be and cannot be used to resolve DBRefs in the server side.
See what the documentation has to say:
The map function should not access the database for any reason.
The map function should be pure, or have no impact outside of the
function (i.e. side effects.)
The reduce function should not access the database, even to perform
read operations. The reduce function should not affect the outside
system.
Moreover, a reduce function even if used(which can never work anyway) will never be called for your problem, since a group w.r.t "fileName" or "ObjectId" would always have only one document, in your dataset.
MongoDB will not call the reduce function for a key that has only a
single value

MongoDB Query double nested documents in array

I was wondering how I can query from an embedded document inside an array. I have following structure:
{ "targetId" : 2, "metaData" : [ { "key" : "id", "value" : 1 }, { "key" : "name", "value" : "Parisa" }, { "key" : "img", "value" : { "imgid" : 1, "imgName" : "img1" } } ]
I could search simple key-values like key = id and value =1, but I could not search based on the values with embedded document e.g. key="img"
I tried following query but it does not work:
db.test.find({"metaData":{$elemMatch:{"key":"img", "value":{"imgid":1}}}})
Could you please help me!
I think the "value" part of your query is a little off. You need to put the document element in the criteria:
b.test.find({"metaData":{$elemMatch:{"key":"img", "value.imgid":1}}})

Filter list of embedded documents with reference field

I'm pretty new to MongoDB and I'm experiencing it with mongoengine.
Given this 'User' model where 'bets' is an embedded document list which each element contains a reference to a 'match' document,
{
"_id" : ObjectId("53df77cef4c9610f28cbff14"),
"name" : "Test",
"admin" : false,
"bets" : [
{ "match" : ObjectId("53e1511df4c9610bf52f5b7a"), "expectedResult" : "1" }
]
}
how can I get 'bets' elements, passed to query the matchId?
I tried to do
User.objects.filter(bets__match={'match._id':match.id})
where 'match' is the object I need to filter by but I get an empty array.