How to achieve the following using MongoDB - mongodb

I used switch statement to assign some text based on different value ; here it returns correct output.
Now from the above output ,again I need to filter out few documents using regular expression.
Some thing like "where status likes 'open%'"
db.accountMailLog.aggregate([
{$match:{'$and': [{recipientId: "3003590"}, {recipientType: "2"}
]}},
{$project :
{
'_id' : 0,
'logCreated' : '$eventOccurredTime',
'subject' : 1,
'resourceType' : 'email',
'campaignName' : 1,
'emailSendDay' : 1,
'logDate' : '$eventOccurredTime',
'sentMethod' : 'campaign-email',
'visitorKey' : '',
'mediaHash' : '',
"status" : {'$switch' :
{'branches' :
[
{'case' : {'$eq' : ['$status','1']},'then' : "delivered"},
{'case' : {'$eq' : ['$status','2']},'then' : "opened"},
{'case' : {'$eq' : ['$status','3']},'then' : "clicked"},
{'case' : {'$eq' : ['$status','4']},'then' : "bounced"},
{'case' : {'$eq' : ['$status','5']},'then' : "unsubscribed"},
{'case' : {'$eq' : ['$status','6']},'then' : "complained"}
]
}
}
}},
]);
Thanks !!!

You can use Regexp. Something like:
"status": open/

Related

MongoDB aggregate return averages only where date key is greater than a specific date in PyMongo

I have a collection that looks something like this;
{_id: 1204187,
'name' : 'name',
'date' : 2020-06-21T00:00:00.000+00:00,
'metric_a' : 88.14502,
'metric_b' : 31.26421,
'metric_c' : 1544.32414,
'info' : {'foreign_key' : 156789,
'country' : 'US',
'tags' : ['a', 'b', 'c']}}
I would like to return aggregated docs, but only aggregate documents where the date is greater than 7-1-2020.
Here is my first attempt;
date_obj = dt.datetime(today.year, today.month, 1)
docs = loads(dumps(collection.aggregate(
[{
'$match' : {
'_id' : '$name',
'metric_a' : {'$avg' : '$metric_a'},
'metric_b' : {'$avg' : '$metric_b'},
metric_c: {'$avg' : '$metric_c'},
},'$match' : {'date' : {'$gte' : date_obj}}
}])))
This ends up grouping each document with a different date separately. What am I missing?
Found a solution;
docs = loads(dumps(collection.aggregate(
[
{'$match' : {'date' : {'$gte' : date_obj}}},
{
'$group' : {
'_id' : '$name',
'metric_a' : {'$avg' : '$metric_a'},
'metric_b' : {'$avg' : '$metric_b'},
'metric_c' : {'$avg' : '$metric_c'},
'info' : {'$last' : '$info'}
}
}
])))
Pretty intuitive, set conditions first and then how and what you want returned.

Mongodb put Documents array as the same level

I have this array of documents, I would like to put "table" on the same level like mastil_antenas and other variables. how Can I do that with aggregate?
I'm trying with the aggregate $project but I can't get the result.
Example of Data
[ {
"mastil_antena" : "1",
"nro_platf" : "1",
"antmarcmast" : "ANDREW",
"antmodelmast" : "HWXXX6516DSA3M",
"retmarcmast" : "Ericsson",
"retmodelmast" : "ATM200-A20",
"distmast" : "1.50",
"altncramast" : "41.30",
"ORIENTMAG" : "73.00",
"incelecmast" : "RET",
"incmecmast" : "1.00",
"Feedertypemast" : "Fibra Optica",
"longjumpmast" : "5.00",
"longfo" : "100",
"calibrecablefuerza" : "10 mm",
"longcablefuerza" : "65.00",
"modelorruantena" : "32B66A",
"tiltmecfoto" : "https://secure.appenate.com/Files/FormEntry/47929-92cdf219-3128-4903-8324-a81000602b9d171017114934746000.jpg",
"tiltmecfoto_fh" : "2017-10-18T05:51:22Z",
"az0foto" : "https://secure.appenate.com/Files/FormEntry/47929-92cdf219-3128-4903-8324-a81000602b9d171017115012727000.jpg",
"az0foto_fh" : "2017-10-18T05:55:21Z",
"azneg60foto" : "https://secure.appenate.com/Files/FormEntry/47929-92cdf219-3128-4903-8324-a81000602b9d171017115016199000.jpg",
"azneg60foto_fh" : "2017-10-18T05:55:36Z",
"azpos60foto" : "https://secure.appenate.com/Files/FormEntry/47929-92cdf219-3128-4903-8324-a81000602b9d171017115020147000.jpg",
"azpos60foto_fh" : "2017-10-18T05:55:49Z",
"etiqantenafoto" : "https://secure.appenate.com/Files/FormEntry/47929-92cdf219-3128-4903-8324-a81000602b9d171017114920853000.jpg",
"etiqantenafoto_fh" : "2017-10-18T05:56:01Z",
"tiltelectfoto" : "https://secure.appenate.com/Files/FormEntry/47929-92cdf219-3128-4903-8324-a81000602b9d171017114914236000.jpg",
"tiltelectfoto_fh" : "2017-10-18T05:56:13Z",
"idcablefoto" : "https://secure.appenate.com/Files/FormEntry/47929-92cdf219-3128-4903-8324-a81000602b9d171017114900279000.jpg",
"idcablefoto_fh" : "2017-10-18T05:56:38Z",
"rrutmafoto" : "https://secure.appenate.com/Files/FormEntry/47929-92cdf219-3128-4903-8324-a81000602b9d171017114947279000.jpg",
"rrutmafoto_fh" : "2017-10-18T05:56:49Z",
"etiquetarrufoto" : "https://secure.appenate.com/Files/FormEntry/47929-92cdf219-3128-4903-8324-a81000602b9d171017114954648000.jpg",
"etiquetarrufoto_fh" : "2017-10-18T05:57:02Z",
"rrutmafoto1" : "https://secure.appenate.com/Files/FormEntry/47929-92cdf219-3128-4903-8324-a81000602b9d171017114959738000.jpg",
"rrutmafoto1_fh" : "2017-10-18T05:57:12Z",
"etiquetarrufoto1" : "https://secure.appenate.com/Files/FormEntry/47929-92cdf219-3128-4903-8324-a81000602b9d171017115005545000.jpg",
"etiquetarrufoto1_fh" : "2017-10-18T05:57:27Z",
"botontorre4" : "sstelcel3",
"table" : { /* put all varibles one level up*/
"tecmast" : "LTE",
"frecmast" : "2100",
"secmast" : "1",
"untitled440" : "Salir"
},
"comentmast" : "",
"longfeedmast" : "",
"numtmasmast" : "",
"otra_marca_antena" : "",
"otro_modelo_antena" : ""
}]
Starting from MongoDB version 3.4 you could use $addFields to do this.
//replace products with what makes sense in your database
db.getCollection('products').aggregate(
[
{ //1 add the properties from subdocument table to documents
$addFields: {
"documents.tecmast" : "documents.0.table.tecmast",
"documents.frecmast" : "documents.0.table.frecmast",
"documents.secmast" : "documents.0.table.secmast",
"documents.untitled440" : "documents.0.table.untitled440"
}
},
{
//(optional) 2 remove the table property from the documents
$project: {"documents.table" : 0}
}
]
)
Step 1: use $addFields to grab properties from table inside documents.table and put them on documents
Step 2: (optional) remove property "table" from documents.
I hope this helps!!!

How to find something from an array in mongo

{
"_id" : ObjectId("586aac4c8231ee0b98458045"),
"store_code" : NumberInt(10800),
"counter_name" : "R.N.Electric",
"address" : "314 khatipura road",
"locality" : "Khatipura Road (Jhotwara)",
"pincode" : NumberInt(302012),
"town" : "JAIPUR",
"gtm_city" : "JAIPUR",
"sales_office" : "URAJ",
"owner_name" : "Rajeev",
"owner_mobile" : "9828024073",
"division_mapping" : [//this contains only 1 element in every doc
{
"dvcode" : "cfc",
"dc" : "trade",
"beatcode" : "govindpura",
"fos" : {
"_id" : ObjectId("586ab8318231ee0b98458843"),
"loginid" : "9928483483",
"name" : "Arpit Gupta",
"division" : [
"cfc",
"iron"
],
"sales_office" : "URAJ", //office
"gtm_city" : "JAIPUR" //city
},
"beat" : {
"_id" : ObjectId("586d372b39f64316b9c3cbd7"),
"division" : {
"_id" : ObjectId("5869f8b639f6430fe4edee2a"),
"clientdvcode" : NumberInt(40),
"code" : "cfc",
"name" : "Cooking & Fabric Care",
"project_code" : "usha-fos",
"client_code" : "usha",
"agent_code" : "v5global"
},
"beatcode" : "govindpura",
"sales_office" : "URAJ",
"gtm_city" : "JAIPUR",
"active" : true,
"agency_code" : "v5global",
"client_code" : "USHA_FOS",
"proj_code" : "usha-fos",
"fos" : {
"_id" : ObjectId("586ab8318231ee0b98458843"),
"loginid" : "9928483483",
"name" : "Arpit Gupta",
"division" : [
"cfc",
"iron"
],
"sales_office" : "URAJ",
"gtm_city" : "JAIPUR"
}
}
}
],
"distributor_mail" : "sunil.todi#yahoo.in",
"project_code" : "usha-fos",
"client_code" : "usha",
"agent_code" : "v5global",
"distributor_name" : "Sundeep Electrical"
}
I am having only 1 element in division_mapping's array and I want to find those documents whose dc in division_mapping is trade.
I have tried following:
"division_mapping":{$elemMatch:{$eq:{"dc":"trade"}}}})
Dont know what I am doing wrong.
//Maybe I have to unwind the array but is there any other way?
According to MongoDB documentation
The $elemMatch operator matches documents that contain an array
field with at least one element that matches all the specified query
criteria.
According to above mentioned description to retrieve only documents whose dc in division_mapping is trade please try executing below mentioned query
db.collection.find({division_mapping:{$elemMatch:{dc:'trade'}}})

Mongoid query embedded document and return parent

I have this document, each is a tool:
{
"_id" : ObjectId("54da43aea96ddcc40915a457"),
"checked_in" : false,
"barcode" : "PXJ-234234",
"calibrations" : [
{
"_id" : ObjectId("54da46ec546173129d810100"),
"cal_date" : null,
"cal_date_due" : ISODate("2014-08-06T00:00:00.000+0000"),
"time_in" : ISODate("2015-02-10T17:46:20.250+0000"),
"time_out" : ISODate("2015-02-10T17:46:20.250+0000"),
"updated_at" : ISODate("2015-02-10T17:59:08.796+0000"),
"created_at" : ISODate("2015-02-10T17:59:08.796+0000")
},
{
"_id" : ObjectId("5509e815686d610b70010000"),
"cal_date_due" : ISODate("2015-03-18T21:03:17.959+0000"),
"time_in" : ISODate("2015-03-18T21:03:17.959+0000"),
"time_out" : ISODate("2015-03-18T21:03:17.959+0000"),
"cal_date" : ISODate("2015-03-18T21:03:17.959+0000"),
"updated_at" : ISODate("2015-03-18T21:03:17.961+0000"),
"created_at" : ISODate("2015-03-18T21:03:17.961+0000")
},
{
"_id" : ObjectId("5509e837686d610b70020000"),
"cal_date_due" : ISODate("2015-03-18T21:03:51.189+0000"),
"time_in" : ISODate("2015-03-18T21:03:51.189+0000"),
"time_out" : ISODate("2015-03-18T21:03:51.189+0000"),
"cal_date" : ISODate("2015-03-18T21:03:51.189+0000"),
"updated_at" : ISODate("2015-03-18T21:03:51.191+0000"),
"created_at" : ISODate("2015-03-18T21:03:51.191+0000")
}
],
"group" : "Engine",
"location" : "Here or there",
"model" : "ZX101C",
"serial" : NumberInt(15449),
"tool" : "octane analyzer",
"updated_at" : ISODate("2015-09-30T20:43:55.652+0000"),
"description" : "Description...",
}
Tools are calibrated periodically. What I want to do is grab tools that are due this month.
Currently, my query is this:
scope :upcoming, -> { where(:at_ats => false).where('calibrations.0.cal_date_due' => {'$gte' => Time.now-1.day, '$lte' => Time.now+30.days}).order_by(:'calibrations.cal_date_due'.asc) }
However, this query gets the tool by the first calibration object and it needs to be the last. I've tried a myriad of things, but I'm stuck here.
How can I make sure I'm querying the most recent calibration document, not the first (which would be the oldest and therefore not relevant)?
You should look into aggregation framework and $unwind operator.
This link may be of help.
This link may be helpful. It contains an example of use of 'aggregation framework' for get the last element of the array, that is, the most recent in your case.

mongodb query find in array

I struggle with a find query.
I have two documents in a mongodb grid collection:
{
"_id" : ObjectId("55b8ac2c1a80142e7f7b23cd"),
"metadata" : {
"filename" : "test2.xml",
"contentType" : "application/xml"
},
"data" : {
"type_file" : "test",
"vision_id" : "6987"
},
"filename" : "test2.xml",
"uploadDate" : ISODate("2015-07-29T10:34:20.991Z"),
"length" : NumberLong(9582),
"chunkSize" : NumberLong(261120),
"md5" : "ea40283994f451b357555e53d186ed1e"
}
{
"_id" : ObjectId("55b8ac2c1a80142e7f7b23cd"),
"metadata" : {
"filename" : "test.xml",
"contentType" : "application/xml"
},
"data" : {
"type_file" : "test",
"vision_id" : "1282"
},
"filename" : "test.xml",
"uploadDate" : ISODate("2015-07-29T10:34:20.991Z"),
"length" : NumberLong(9582),
"chunkSize" : NumberLong(261120),
"md5" : "ea40283994f451b357555e53d186ed1e"
}
Now I want to make a query which retreive the document where "filename" = "test.xml" and the tag "vision_id" = "1282".
Now I made the search query like this:
$query =
array('$and' =>
array(
array("filename" => "text.xml),
array("data" => array("vision_id" => "1282")),
),
);
$cursor = $gridFS->find($query)
If I run this I don't get a result:
When I remove the line array("data" => array("vision_id" => "1282")), then I get the last document. (As I predicted).
Could anybody give me a push to the right way, to search also within the data array?
Kind Regards,
Arjan Kroon
I found the solution.
$query =
array('$and' =>
array(
array("filename" => "text.xml"),
array("data.vision_id" => "1282"),
),
);