Related
I'm kindly requesting your help for this query that I need to do and I'm not very proficient yet in MongoDB. My data structure looks like this:
db.getCollection('EventDateValidation').find({}):
/* 1 */
{
"_id" : ObjectId("5b7b2e3ae5e2100007717d81"),
"_class" : "com.overwatch.common.model.EventDateValidation",
"caseNo" : "OW000002269122201810201135",
"loanNo" : "000002269122",
"eventType" : "BREACLETTR",
"validationStepData" : [
{
"startDate" : {
"isChecked" : "Y",
"comments" : "",
"auditedBy" : "Mahalakshmi M",
"auditedDate" : "2018-12-12"
}
},
{
"completedDate" : {
"isChecked" : "Y",
"comments" : "",
"auditedBy" : "Mahalakshmi M",
"auditedDate" : "2018-12-13"
}
},
{
"deadlineDate" : {
"isChecked" : "Y",
"comments" : "",
"auditedBy" : "Mahalakshmi M",
"auditedDate" : "2018-12-13"
}
}
]
}
/* 2 */
{
"_id" : ObjectId("5b7c11095c2b4d0007bc8c54"),
"_class" : "com.overwatch.common.model.EventDateValidation",
"caseNo" : "OW000000854076201808181158",
"loanNo" : "000000854076",
"eventType" : "FORSALAPPR",
"validationStepData" : [
{
"startDate" : {
"comments" : ""
}
},
{
"completedDate" : {
"comments" : "Received Date = 8/4/2017"
}
},
{
"deadlineDate" : {
"comments" : ""
}
}
]
}
/* 3 */
{
"_id" : ObjectId("5b7ad05d5c2b4d0007bc8631"),
"_class" : "com.overwatch.common.model.EventDateValidation",
"caseNo" : "OW000000873954201810201235",
"loanNo" : "000000873954",
"eventType" : "HUDNOTIFCA",
"validationStepData" : [
{
"startDate" : {
"isChecked" : "Y",
"comments" : "",
"auditedBy" : "Brett Scott",
"auditedDate" : "2018-09-25"
}
},
{
"completedDate" : {
"isChecked" : "Y",
"comments" : "",
"auditedBy" : "Brett Scott",
"auditedDate" : "2018-09-25"
}
},
{
"deadlineDate" : {
"isChecked" : "Y",
"comments" : "",
"auditedBy" : "Brett Scott",
"auditedDate" : "2018-09-25"
}
}
]
}
From this collection, I need to find the documents that have an "auditedDate" in the "deadlineDate". In this example, I would find the documents 1 and 3. Please help me as I'm stuck on this one.
I have tried
db.getCollection('EventDateValidation').find({"validationStepData.deadlineDate.auditedDate":{$exists:true}})
But doesn't seem to work. Help please!
Just for clearing things up: the query in the question works well. I chatted with #Gabriel, and the problem was that Robomongo added hidden non-printable unicode characters to the query.
All in all, for any interested nomads, here are few ways to query an array of objects:
1) Implicit $elemMatch / simple dot notation on an array:
db.getCollection('EventDateValidation').find({"validationStepData.deadlineDate.auditedDate": {$exists:true}})
2) Explicit $elemMatch (we can have multiple query criteria):
db.getCollection('EventDateValidation').find({"validationStepData": { $elemMatch: {"deadlineDate.auditedDate" : {$exists:true} }}})
3) Array dot notation with an index position (when we know the exact position of an element inside an array):
db.getCollection('EventDateValidation').find({"validationStepData.2.deadlineDate.auditedDate": {$exists:true}})
Dot notation wouldn't work since you have an array of objects within validationStepData. You could use $elemMatch to apply your query conditions to the array elements that match your expression.
db.getCollection('EventDateValidation').find({"validationStepData" : { $elemMatch: {"deadlineDate.auditedDate" : {$exists:true} }}})
I have an document that contains array of arrays i am using embedded document in MongoDb.Say i have collection name Orders looks like:-
"_id" : "HjPGrdkffg7dQPtiX",
"ListOrdersResult" : [
{
"Orders" : {
"Order" : [
{
"LatestShipDate" : "2016-01-13T18:29:59Z",
"OrderType" : "StandardOrder",
"PurchaseDate" : "2016-01-11T10:24:49Z",
"PaymentExecutionDetail" : {
"PaymentExecutionDetailItem" : {
"PaymentMethod" : "COD",
"Payment" : {
"CurrencyCode" : "INR",
"Amount" : "839.30"
}
}
},
"BuyerEmail" : "vccdbptpx2ssd74882#marketplace.amazon.in",
"AmazonOrderId" : "402-4031538-7451469",
"LastUpdateDate" : "2016-01-14T06:47:17Z",
"ShipServiceLevel" : "IN Exp Dom 2",
"NumberOfItemsShipped" : "1",
"OrderStatus" : "Shipped",
"SalesChannel" : "Amazon.in",
"ShippedByAmazonTFM" : "false",
"LatestDeliveryDate" : "2016-01-19T18:29:59Z",
"NumberOfItemsUnshipped" : "0",
"BuyerName" : "xyz",
"EarliestDeliveryDate" : "2016-01-13T18:30:00Z",
"OrderTotal" : {
"CurrencyCode" : "INR",
"Amount" : "839.30"
},
"IsPremiumOrder" : "false",
"EarliestShipDate" : "2016-01-11T18:30:00Z",
"MarketplaceId" : "A21TJRRWUN4KGVC",
"FulfillmentChannel" : "MFN",
"TFMShipmentStatus" : "Delivered",
"PaymentMethod" : "COD",
"ShippingAddress" : {
"StateOrRegion" : "HARYANA",
"City" : "GURGAON",
"Phone" : "9999999999",
"CountryCode" : "IN",
"PostalCode" : "122001",
"Name" : "Murthy",
"AddressLine1" : "House No. , J Block, Badshahpur"
},
"IsPrime" : "false",
"ShipmentServiceLevelCategory" : "Expedited"
},
{
"LatestShipDate" : "2016-01-13T18:29:59Z",
"OrderType" : "StandardOrder",
"PurchaseDate" : "2016-01-11T13:16:49Z",
"PaymentExecutionDetail" : {
"PaymentExecutionDetailItem" : {
"PaymentMethod" : "COD",
"Payment" : {
"CurrencyCode" : "INR",
"Amount" : "899.40"
}
}
},
"BuyerEmail" : "xyz#marketplace.amazon.in",
"AmazonOrderId" : "402-2142159-5087541",
"LastUpdateDate" : "2016-01-14T06:47:15Z",
"ShipServiceLevel" : "IN Exp Dom 2",
"NumberOfItemsShipped" : "1",
"OrderStatus" : "Cancel",
"SalesChannel" : "Amazon.in",
"ShippedByAmazonTFM" : "false",
"LatestDeliveryDate" : "2016-01-19T18:29:59Z",
"NumberOfItemsUnshipped" : "0",
"BuyerName" : "demo prakash",
"EarliestDeliveryDate" : "2016-01-13T18:30:00Z",
"OrderTotal" : {
"CurrencyCode" : "INR",
"Amount" : "899.40"
},
"IsPremiumOrder" : "false",
"EarliestShipDate" : "2016-01-11T18:30:00Z",
"MarketplaceId" : "A21TJEUUN4WGV",
"FulfillmentChannel" : "MFN",
"TFMShipmentStatus" : "Delivered",
"PaymentMethod" : "COD",
"ShippingAddress" : {
"StateOrRegion" : "DELHI",
"City" : "DELHI",
"Phone" : "99999999",
"CountryCode" : "IN",
"PostalCode" : "110038",
"Name" : "Demo prakash",
"AddressLine1" : "Hn 638 gali n 04 Wazirabad new delhi"
},
"IsPrime" : "false",
"ShipmentServiceLevelCategory" : "Expedited"
},
}
]
},
"CreatedBefore" : "2015-03-19T06:17:59Z"
}
],
"ResponseMetadata" : {
"RequestId" : "cf94645e-ada7-4ec6-b161-a97d07a77817"
},
"seller_user_id" : "yg4e34ccodzf3GPR2",
}
So as you can see this is the single document that contains the whole data of array i want to fetch the orders whose status is cancel from this order array.
So for that i have use :-
var orderDetails =
orders.find({"ListOrdersResult.Orders.Order":{$elemMatch:
{ OrderStatus:"Canceled"}}}).fetch();
Also i tried with:-
orders.find({"ListOrdersResult.Orders.Order.OrderStatus":'Canceled'}).fetch();
So this will return the whole document that contains status as canceled and other as well but i want only selected result from the document that contains status as pending.
So is there any way in mongoDb to query a selected value from a single document that contains nested array of arrays as object.
Or I need to staore the values into diff diff documents thats only the solution.
Any help would be appriciated please contribute
Thanks!
You can go with any meteor aggregate package. You can use match and then group the data then send it to client-side.Like :
var ordersLines = orders.aggregate([
{$unwind : "$ListOrdersResult.Orders.Order"},
{$match : { OrderStatus:"Canceled"} },
{$project : {
OrderType : '$ListOrdersResult.Orders.Order.OrderType'
....
}
}
]);
return ordersLines;
But I suggest you go with a different document.
I am trying to get only the ObjectId's from One specific Document that is embedded in the projects Array.
Basically I am trying to make a database that will have users and each user will have there own projects.
Thank you !
db.users.find().pretty()
{
"_id" : ObjectId("5762c0cf2b9a78006373a684"),
"name" : "seq",
"pass" : "seq",
"projects" : [
{
"pid" : ObjectId("5762c0ba2b9a78006373a682"),
"name" : "aaa"
},
{
"pid" : ObjectId("5762c0ba2b9a78006373a683"),
"name" : "bbb"
}
]
}
{
"_id" : ObjectId("5762c28d2b9a78006373a687"),
"name" : "leq",
"pass" : "leq",
"projects" : [
{
"pid" : ObjectId("5762c2892b9a78006373a685"),
"name" : "ccc"
},
{
"pid" : ObjectId("5762c2892b9a78006373a686"),
"name" : "ddd"
}
]
}
let say we want two pids
{"pid" : ObjectId("5762c0ba2b9a78006373a682")} and
{"pid" : ObjectId("5762c2892b9a78006373a686"),}
and only inner documents
so required response should look like:
{
"_id" : ObjectId("5762c0ba2b9a78006373a682"),
"name" : "aaa"
},{
"_id" : ObjectId("5762c2892b9a78006373a686"),
"name" : "ddd"
}
Aggregation framework can manipulate documents, match only needed ones and transform inner structure by project phase:
var match = {
$match : {
"projects.pid" : {
$in : [ObjectId("5762c0ba2b9a78006373a682"),
ObjectId("5762c2892b9a78006373a686")]
}
}
}
var unwind = {
$unwind : "$projects"
};
// now move array objet as top level object
var project = {
$project : {
_id : "$projects.pid",
name : "$projects.name",
// list other fields here
}
}
db.vic.aggregate([match, unwind, match, project])
I have following data.
{
"name" : "Maria",
"facebook" : [
{
"data" : "fb.com",
"privacy" : true
}
],
"twitter" : [
{
"data" : "twitter.com",
"privacy" : false
}
],
"google" : [
{
"data" : "google.com",
"privacy" : true
}
],
"phno" : [
{
"data" : "+1-1289741824124",
"privacy" : true
}
]
}
I want to return only data having privacy is equal to true. How do I do it ?
I tried but it returns all data having privacy is equal to false also. How do I query the data ?
Please post MongoDB query not Javascript code.
Thanks!
edit
having structure like this:
{
"_id" : ObjectId("575e4c8731dcfb59af388e1d"),
"name" : "Maria",
"providers" : [
{
"type" : "facebook",
"data" : "fb.com",
"privacy" : true
},
{
"type" : "twitter",
"data" : "twitter.com",
"privacy" : false
},
{
"type" : "google",
"data" : "google.com",
"privacy" : true
},
{
"type" : "phno",
"data" : "+1-1289741824124",
"privacy" : true
}
]
}
with query like this:
db.maria.aggregate([{
$project : {
_id : 1,
name : 1,
"providers" : {
$filter : {
input : "$providers",
as : "p",
cond : {
$eq : ["$$p.privacy", true]
}
}
}
}
}
])
])
we are gaining dynamic output, and we don't need to take care about provider name as this is covered by generic structure
{
"providers" : [
{
"type" : "facebook",
"data" : "fb.com",
"privacy" : true
},
{
"type" : "google",
"data" : "google.com",
"privacy" : true
},
{
"type" : "phno",
"data" : "+1-1289741824124",
"privacy" : true
}
],
"name" : "Maria"
}
end of edit
The way you could get this is using aggregation framework.
As we have an array for each field, we need to unwind it first, then we can use $project to set field value or simply null. As this looks like a simple query, it could give a bit of trouble. The way we can improve that is change a document structure, to have an array of providers and simple providerType field.
Aggregation stages below:
db.maria.find()
var unwindFb = {
$unwind : "$facebook"
}
var unwindtw = {
$unwind : "$twitter"
}
var unwindgo = {
$unwind : "$google"
}
var unwindph = {
$unwind : "$phno"
}
var project = {
$project : {
_id : 1,
name : 1, // list other fields here
facebook : {
$cond : {
if : {
$gte : ["$facebook.privacy", true]
},
then : [{
data : "$facebook.data",
privacy : "$facebook.privacy"
}
],
else : null
}
},
twitter : {
$cond : {
if : {
$gte : ["$twitter.privacy", true]
},
then : [{
data : "$twitter.data",
privacy : "$twitter.privacy"
}
],
else : null
}
},
google : {
$cond : {
if : {
$gte : ["$google.privacy", true]
},
then : [{
data : "$google.data",
privacy : "$google.privacy"
}
],
else : null
}
},
phno : {
$cond : {
if : {
$gte : ["$phno.privacy", true]
},
then : [{
data : "$phno.data",
privacy : "$phno.privacy"
}
],
else : null
}
}
}
}
db.maria.aggregate([unwindFb, unwindtw, unwindgo, unwindph, project])
then output looks like this:
{
"_id" : ObjectId("575df49d31dcfb59af388e1a"),
"name" : "Maria",
"facebook" : [
{
"data" : "fb.com",
"privacy" : true
}
],
"twitter" : null,
"google" : [
{
"data" : "google.com",
"privacy" : true
}
],
"phno" : [
{
"data" : "+1-1289741824124",
"privacy" : true
}
]
}
you can use the below code to iterate the object and check for the privacy true
var list = {
"name" : "Maria",
"facebook" : [
{
"data" : "fb.com",
"privacy" : true
}
],
"twitter" : [
{
"data" : "twitter.com",
"privacy" : false
}
],
"google" : [
{
"data" : "google.com",
"privacy" : true
}
],
"phno" : [
{
"data" : "+1-1289741824124",
"privacy" : true
}
]
}
$.each(Object.keys(list), function(index,value){
if(list[value][0].privacy)
{
console.log(list[value][0]);
}
});
If you are open to use lodash ...this is how you can do it...
var tmp = {
...you json here
}
var res =[];//result array of filtered data
_.forIn(tmp, function (o) {
if (Array.isArray(o)) {
if (o[0].privacy === true) {
res.push(o);
}
}
});
This question already has an answer here:
Updating template with session variable and subscription/publication only updates with previous query and appends information
(1 answer)
Closed 7 years ago.
Description of the problem:
I have two collections videos and specs. videos collection has a key called spec which corresponds to a specs id. Both collections are not empty.
My Template Helper:
Template.List.helpers({
videos: function(){
var vids = Videos.find({ online: false}).fetch();
return vids.map(function(value){
console.log("id: " + value.spec);
console.log(Specs.find({ id: value.spec }).fetch());
//Issue here
value.specName = Specs.find({ id: value.spec }).fetch()[0].name;
return value;
});
}
});
As you can see in my template helper I loop through the video array and add specName to the array.
The main problem comes from this specific line:
value.specName = Specs.find({ id: value.spec }).fetch()[0].name;
and more specifically this line: Specs.find({ id: value.spec }).fetch()
which will return null every time.
What I've tried:
Naturally, my first thought would be to check what value.spec returns. And it returns an int between 1 and 15 (included) which is right. If value.spec is right, then how come the find() doesn't return anything?
I then decided to hard set it and tried this:
Specs.find({ id: 2}).fetch()
And this worked. Which is weird because on multiple occasions value.spec returns 2...
I've also tried intParse(value.spec) just in case, however that didn't work either.
Question
Why does Specs.find({ id: value.spec }).fetch() return null knowing that value.spec is set correctly and that a hard coded number works?
Requested json data: (from meteor mongo)
specs:
{ "_id" : "XKXHtQuiFsAew3dDy", "id" : 1, "name" : "Endocrine surgery" }
{ "_id" : "68jFidAMXTXpQtQye", "id" : 2, "name" : "General and digestive" }
{ "_id" : "GZSXToRXMfJgnH3CY", "id" : 3, "name" : "Pediatric surgery" }
{ "_id" : "T2mBz2gsXEqQaybmq", "id" : 4, "name" : "Thoracic surgery" }
{ "_id" : "hnuQzZiPKvYYDZhc8", "id" : 5, "name" : "Equipment" }
{ "_id" : "byE3A6HchvfhKdmR8", "id" : 6, "name" : "Gynecology" }
{ "_id" : "u5rrPB7asGW3NC6B2", "id" : 7, "name" : "Urology" }
{ "_id" : "umxKvR66oEx5dRppf", "id" : 8, "name" : "Cardiovascular surgery" }
{ "_id" : "bPcBTZn3t5ubRRcrQ", "id" : 9, "name" : "Endoscopic surgery" }
{ "_id" : "yNyAqQPoreNtdRZ34", "id" : 10, "name" : "NOTES" }
{ "_id" : "KG794eakRaztEqehG", "id" : 11, "name" : "Robotic surgery" }
{ "_id" : "QBrtvTg4GT7Tf7cAJ", "id" : 12, "name" : "Skull base surgery" }
{ "_id" : "HEhq6oBjuuMnrxE5a", "id" : 13, "name" : "Arthroscopy and upper limb surgery" }
{ "_id" : "xwpgHqZpBQP7WAnd5", "id" : 14, "name" : "Single port surgery" }
{ "_id" : "K4BgFupwNdDGD3449", "id" : 15, "name" : "Telemicrosurgery" }
videos:
{ "_id" : "L5Qi7YRRhn6Sfcjk8", "id" : "vd01en1065e", "title" : "Right inguinal hernia: open plug technique", "authors" : [ "E Pelissier" ], "date_published" : "2004-09-27", "abstract" : "", "tags" : [ "" ], "spec" : 2, "private" : true, "online" : false }
{ "_id" : "M8cuLW6KNCqKeP9vF", "id" : "vd01en1074e", "title" : "Laparoscopic splenectomy, posterior approach", "authors" : [ "D Mutter", " F Rubino" ], "date_published" : "2004-09-27", "abstract" : "", "tags" : [ "" ], "spec" : 2, "private" : true, "online" : false }
{ "_id" : "Ptzrxw8GifeMvQk9k", "id" : "vd01en1090e", "title" : "Intussusception of the intestine in the newborn", "authors" : [ "F Becmeur", " D Christmann", " I Kauffmann" ], "date_published" : "2004-09-27", "abstract" : "", "tags" : [ "" ], "spec" : 3, "private" : true, "online" : false }
{ "_id" : "oHWcX3vCBHuZQM9hR", "id" : "vd01en1103e_2", "title" : "Appendicular peritonitis: laparoscopic conversion", "authors" : [ "B Navez" ], "date_published" : "2001-11-05", "abstract" : "", "tags" : [ "" ], "spec" : 2, "private" : true, "online" : false }
{ "_id" : "6uzmxYxhd5DDuS2gG", "id" : "vd01en1108e", "title" : "Diaphragmatic hernias", "authors" : [ "F Becmeur" ], "date_published" : "2001-11-28", "abstract" : "", "tags" : [ "" ], "spec" : 3, "private" : true, "online" : false }
{ "_id" : "yHqruiQYeeQ9SDHpH", "id" : "vd01en1112e", "title" : "Laparoscopic excision of the cystic stump", "authors" : [ "J Leroy" ], "date_published" : "2004-09-27", "abstract" : "", "tags" : [ "" ], "spec" : 2, "private" : true, "online" : false}
{ "_id" : "fmjtk5WAEKitMxyGj", "id" : "vd01en1114e", "title" : "Laparoscopic gastric banding in a patient with a BMI of 40", "authors" : [ "JM Zimmermann", " D Fölscher" ], "date_published" : "2004-09-27", "abstract" : "", "tags" : [ "" ], "spec" : 2, "private" : true, "online" : false}
I've been stuck on this problem for a couple hours, I didn't want to post this on SO since I do believe it's a simple problem. However, it is mind boggling.
The problem here is the publication/subscription issue. You did not mention it, how do you handle publications and subscriptions but that is most likely the issue. What is happening is that when you browse your videos collection, which subscription is ready (since you hae any data in it) here: Videos.find({ online: false}) that not necessarly means that (in that precise moment) subscription handling Spec collection is ready as well. So even if on the server the query is working, on the client it's null, because the data are not synced between client and server YET. so you have to wait until both subscriptions are ready somehow. You can use template subscriptions, or waitOn function in your router.
First of all check on server side that your publication and subscription is ready and returning you back data check this like as
Meteor.publish('Videso', function () {
var result= Videso.find({});
console.log(result);
return result
});
if console.log returning you records on server side i have a solution then your
problem
the solution of your problem is that
Template.List.helpers({
videos: function(){
var vids = Videos.find({ online: false}).map(function (value) {
console.log("id: " + value.spec);
var idValue = Specs.findOne({ "id": value.spec })
console.log("idValue===",idValue)
return _.extend(value, idValue);
});
console.log(vids); //here merged data of both table having
// relvent record will returned
return vids;
}
});
Just implement it and check data on your template it will be ready for you and vote me then :)