I'm trying to create this query to use with jasper reports but something is wrong with my syntax, i have 2 ISODates in my db and i want to query between then, in this query I use $match and $gt, $lt.
Anyway something is not correct because the console says error but doesn`t specify it.
Obs: The problem is something with the $match and the $lt and $gt. because without them it is possible to query.
Code:
{
runCommand : {
aggregate : 'saleCalculation',
pipeline : [
{
$match: {
processingInfo.modifiedDate: {$gt : ISODate("2016-05-01T09:29:40.572Z")},
{$lt : ISODate("2016-06-01T09:29:40.572Z")}
}
},
{
$project : {
header.documentCode : 1,
header.transactionDate : 1,
header.metadata.entityName : 1,
lines : 1
}
},
{ $unwind : '$lines'},
{ $unwind :'$lines.calculatedTax.details' }
]
}
}
Jasper Manual says i need to do something like that:
http://community.jaspersoft.com/wiki/how-query-mongo-isodate-data-parameter
but i didn't understand that
Try this code :
{
runCommand : {
aggregate : 'saleCalculation',
pipeline : [
{
$match: {
processingInfo.modifiedDate: {$gt : ISODate("2016-05-01T09:29:40.572Z"),
$lt : ISODate("2016-06-01T09:29:40.572Z")}
}
},
{
$project : {
header.documentCode : 1,
header.transactionDate : 1,
header.metadata.entityName : 1,
lines : 1
}
},
{ $unwind : '$lines'},
{ $unwind :'$lines.calculatedTax.details' }
]
}
}
Try with this pipeline. Make sure to use double quotes.
[
{ "$match": {"processingInfo.modifiedDate": { "$gt":ISODate("2010-03-26T18:40:59.000Z"), "$lt":ISODate("2016-09-28T18:40:59.000Z")}}},
{
"$project" : {
"header.documentCode": 1,
"header.transactionDate": 1,
"header.metadata.entityName": 1,
"lines" : 1
}
},
{ "$unwind": "$lines"},
{ "$unwind": "$lines.calculatedTax.details" }
]
I tried this command on mongo shell and it worked without any error.
db.runCommand({"aggregate": "saleCalculation", "pipeline" : [
{ "$match": {"processingInfo.modifiedDate": { "$gt":ISODate("2010-03-26T18:40:59.000Z"), "$lt":ISODate("2016-09-28T18:40:59.000Z")}}},
{
"$project" : {
"header.documentCode": 1,
"header.transactionDate": 1,
"header.metadata.entityName": 1,
"lines" : 1
}
},
{ "$unwind": "$lines"},
{ "$unwind": "$lines.calculatedTax.details" }
]
})
Related
Here is the sample of one of the documents in our collection in MongoDB. I need to get all the values of the NUMBER field from all the documents in this collection with a MongoDB Query. What could be that Query?
{
"_id" : "5w1669ba-3f8a-4695-a585-9fa510d13e59",
"display_title" : "SWE Test Series!",
"production_year" : "2020",
"type" : "series",
"created_timestamp" : 1597940264,
"seasons" : {
"8c399fbc-dc65-4c2e-b86c-5c6289835b45" : {
"number" : "1",
"uuid" : "8c399fbc-dc65-4c2e-b86c-5c6289835b45",
"created_timestamp" : 1597940441
}
}
}
You can do that.
Play
objectToArray makes it easy.
db.collection.aggregate([
{
"$project": {
"a": {
"$objectToArray": "$seasons"
}
}
},
{
"$unwind": "$a"
},
{
$project: {
"a.v.number": 1
}
}
])
How to use Reactive MongoDB Aggregation Framework in the case when required pipeline stage isn't available?
I'm interested in lookup stage with pipeline, but in documentation I found only
reactivemongo.api.commands.AggregationFramework.Lookup.apply(from: String, localField: String, foreignField: String, as: String)
Development story
Originally code was equivalent to MongoDB JS code
db.tournament.aggregate([
{ $match : { "tid" : "abacaba"} },
{ $group : { _id : "$t" , "m" : {
{ $sort : { "m" : -1 } },
$push : {"u" : "$uid", "m" : "$m" } }
}},
{ $project : { "p" : { $slice : ["$m", 20]} } }
]);
Performance problem with this code that we pushing everything into array and discarding unneeded data only in projection stage. So after reading StackOverflow answer,
I rewrite it to
{ $match : { "tid" : "abacaba"} },
{ $sort : { "m" : -1 } },
{ $group : { "_id" : "$t"} },
{ $lookup : {
"from" : "tournament",
"let" : { "i" : "$_id" },
"pipeline" : [
{ $match : { "$expr" : { "$eq" : [ "$t", "$$i"] } } },
{ $sort : { "m" : -1 } },
{ $limit : 20 },
{ $project : { "uid" : 1, "m" : 1} }
],
"as" : "p"
}}
]);
but I stuck with translating it to Reactive MongoDB Scala code.
UPD1. I accidentally found piece of code with necessary lookup syntax. And came to another question. How Sharded Collection Restrictions looks in my case when the collection on which I run the aggregate() method is equal to from collection?
I would like to output result of my $unwind operation into another collection and getting duplicate _id error. In order to overcome it I am using $group to produce a new _id field. How can I project extra fields from collection? When I am using $project clause it doesn't output anything.
This one works:
db.audit.aggregate([
{$match: { "date": { $gte : ISODate("2015-01-30T00:00:00.000Z"),
$lt : ISODate("2015-01-31T00:00:00.000Z")
}
}
},
{ $unwind : "$data.items" } ,
{ $group : {
"_id" : {
"_id":"$_id",
"sku":"$data.items.sku"
}
}
},
{
$out : "randomAggregates"
}
]
)
This one doesn't:
db.audit.aggregate([
{$match: { "date": { $gte : ISODate("2015-01-30T00:00:00.000Z"),
$lt : ISODate("2015-01-31T00:00:00.000Z")
}
}
},
{ $unwind : "$data.items" } ,
{ $project: { "ccy" : "$data.crncy",
"coo" : "$data.items.coo",
"order_id" : "$meta.refid"
}
},
{ $group : {
"_id" : {
"_id":"$_id",
"sku":"$data.items.sku"
}
}
},
{
$out : "randomAggregates"
}
]
)
Thank you
Use the $first operator in the $group stage and access the whole document using the $$ROOT variable.
{$group:{"_id":{"_id":"$_id","sku":"$data.items.sku"},
"value":{$first:"$$ROOT"}}}
or,
{$group:{"_id":{"_id":"$_id","sku":"$data.items.sku"},
"field":{$first:"$field"}}} // do this for all the fields.
Your modified code would look like:
db.audit.aggregate([
{$match: { "date": { $gte : ISODate("2015-01-30T00:00:00.000Z"),
$lt : ISODate("2015-01-31T00:00:00.000Z")
}
}
},
{ $unwind : "$data.items" } ,
{$group:{"_id":{"_id":"$_id","sku":"$data.items.sku"},
"value":{$first:"$$ROOT"}}} // you could do it for individual
// fields as well here
{
$out : "randomAggregates"
}
]
)
Say I have this:
{
"_id" : "ENVD",
"years" : [
{
"year" : "2013",
"avgInstructor" : 5.144999999999998
},
{
"year" : "2012",
"avgInstructor" : 5.194436090225564
}
]
}
I need to be able to find the difference in the avgInstructor field from 2012-13. I was thinking I could transform the keys somehow using a $project which would make the year be the key, and the avgInstructor rating be the value. So it would look like this:
{
"_id" : "ENVD",
"years" : {
"2013" : 5.144999999999998,
"2012" : 5.194436090225564
}
}
Is this possible? Keep in mind my main goal is to be able to run a subtraction like this pseudocode : years['2013'].avgInstructor - years['2013'].avgInstructor. So if you see an easier way, that would be great as well. I am not sure of the best way to go about this in the context of an aggregation pipeline. Can someone help?
For people that ends up here looking for a solution to transform an array to an object using aggregation in a more recent version of MongoDB:
MongoDB 3.4.4 introduced $arrayToObject
You have to $map years
{
$set: {
years: {
$map: {
input: "$years",
as: "year",
in: [
"$$year.year",
"$$year.avgInstructor"
]
}
}
}
}
to be like this
{
"_id" : "ENVD",
"years": [
["2013", 5.144999999999998],
["2012", 5.194436090225564]
]
}
then use $arrayToObject
{
$set: {
years: {
$arrayToObject: "$years"
}
}
}
Or combine the two steps together
{
$set: {
years: {
$arrayToObject: {
$map: {
input: "$years",
as: "year",
in: [
"$$year.year",
"$$year.avgInstructor"
]
}
}
}
}
}
A Possible answer ...
Unwind first
project to make it a little easier to handle
Sort on _id and then on year
group by _id to pickup the first and the last value
final projection to get subtracted value
db.coll.aggregate ( [
{ "$unwind" : "$years" } ,
{ $project : { "year" : "$years.year", "avgInstructor" : "$years.avgInstructor" } },
{ $sort : { "_id" : 1, "year" : 1 } },
{ $group : { "_id" : "$_id", "val_min" : { $first : "$avgInstructor" }, "val_max" : { $last : "$avgInstructor" } } },
{ $project : { "diff" : { $subtract : [ "$val_min", "$val_max" ] } } }
] )
I have the following MongoDB collection db.students:
/* 0 */
{
"id" : "0000",
"name" : "John"
"subjects" : [
{
"professor" : "Smith",
"day" : "Monday"
},
{
"professor" : "Smith",
"day" : "Tuesday"
}
]
}
/* 1 */
{
"id" : "0001",
"name" : "Mike"
"subjects" : [
{
"professor" : "Smith",
"day" : "Monday"
}
]
}
I want to find the number of subjects for a given student. I have a query:
db.students.find({'id':'0000'})
that will return the student document. How do I find the count for 'subjects'? Is it doable in a simple query?
If query will return just one element :
db.students.find({'id':'0000'})[0].subjects.length;
For multiple elements in cursor :
db.students.find({'id':'0000'}).forEach(function(doc) {
print(doc.subjects.length);
})
Do not forget to check existence of subjects either in query or before check .length
You could use the aggregation framework
db.students.aggregate(
[
{ $match : {'_id': '0000'}},
{ $unwind : "$subjects" },
{ $group : { _id : null, number : { $sum : 1 } } }
]
);
The $match stage will filter based on the student's _id
The $unwind stage will deconstruct your subjects array to multiple documents
The $group stage is when the count is done. _id is null because you are doing the count for only one user and only need to count.
You will have a result like :
{ "result" : [ { "_id" : null, "number" : 187 } ], "ok" : 1 }
Just another nice and simple aggregation solution:
db.students.aggregate([
{ $match : { 'id':'0000' } },
{ $project: {
subjectsCount: { $cond: {
if: { $isArray: "$subjects" },
then: { $size: "$subjects" },
else: 0
}
}
}
}
]).then(result => {
// handle result
}).catch(err => {
throw err;
});
Thanks!