I have a collection messages in database enron.
To show the collection structure I use this command.
db.messages.findOne()
{
"_id" : ObjectId("4f16fc97d1e2d32371003f02"),
"body" : "COURTYARD\n\nMESQUITE\n2300 HWY 67\nMESQUITE, TX 75150\ntel: 972-681-3300\nfax: 972-681-3324\n\nHotel Information: http://courtyard.com/DALCM\n\n\nARRIVAL CONFIRMATION:\n Confirmation Number:84029698\nGuests in Room: 2\nNAME: MR ERIC BASS \nGuest Phone: 7138530977\nNumber of Rooms:1\nArrive: Oct 6 2001\nDepart: Oct 7 2001\nRoom Type: ROOM - QUALITY\nGuarantee Method:\n Credit card guarantee\nCANCELLATION PERMITTED-BEFORE 1800 DAY OF ARRIVAL\n\nRATE INFORMATION:\nRate(s) Quoted in: US DOLLAR\nArrival Date: Oct 6 2001\nRoom Rate: 62.10 per night. Plus tax when applicable\nRate Program: AAA AMERICAN AUTO ASSN\n\nSPECIAL REQUEST:\n NON-SMOKING ROOM, GUARANTEED\n \n\n\nPLEASE DO NOT REPLY TO THIS EMAIL \nAny Inquiries Please call 1-800-321-2211 or your local\ninternational toll free number.\n \nConfirmation Sent: Mon Jul 30 18:19:39 2001\n\nLegal Disclaimer:\nThis confirmation notice has been transmitted to you by electronic\nmail for your convenience. Marriott's record of this confirmation\nnotice is the official record of this reservation. Subsequent\nalterations to this electronic message after its transmission\nwill be disregarded.\n\nMarriott is pleased to announce that High Speed Internet Access is\nbeing rolled out in all Marriott hotel brands around the world.\nTo learn more or to find out whether your hotel has the service\navailable, please visit Marriott.com.\n\nEarn points toward free vacations, or frequent flyer miles\nfor every stay you make! Just provide your Marriott Rewards\nmembership number at check in. Not yet a member? Join for free at\nhttps://member.marriottrewards.com/Enrollments/enroll.asp?source=MCRE\n\n",
"filename" : "2.",
"headers" : {
"Content-Transfer-Encoding" : "7bit",
"Content-Type" : "text/plain; charset=us-ascii",
"Date" : ISODate("2001-07-30T22:19:40Z"),
"From" : "[email protected]",
"Message-ID" : "<32788362.1075840323896.JavaMail.evans@thyme>",
"Mime-Version" : "1.0",
"Subject" : "84029698 Marriott Reservation Confirmation Number",
"To" : [
"[email protected]"
],
"X-FileName" : "eric bass 6-25-02.PST",
"X-Folder" : "\\ExMerge - Bass, Eric\\Personal",
"X-From" : "[email protected]",
"X-Origin" : "BASS-E",
"X-To" : "[email protected]",
"X-bcc" : "",
"X-cc" : ""
},
"mailbox" : "bass-e",
"subFolder" : "personal"
}
I need to get a result of pairs 'from' and 'to'. To do that I use aggregate command. First of all I use {"$unwind": "$headers.To"}
to ungroup all email from array headers.to. Than I use $group section to group my result.
I use this query:
db.messages.aggregate([{"$unwind": "$headers.To"},
{"$group": { "_id":null, 'From': "$headers.From", 'To': "$headers.To","count":{$sum:1}}},
{"$sort": {"count": -1}},
{"$limit": 10},
])
Error message:
assert: command failed: {
"ok" : 0,
"errmsg" : "the group aggregate field 'From' must be defined as an expression inside an object",
"code" : 15951
} : aggregate failed
_getErrorWithCode@src/mongo/shell/utils.js:25:13
doassert@src/mongo/shell/assert.js:13:14
assert.commandWorked@src/mongo/shell/assert.js:287:5
DBCollection.prototype.aggregate@src/mongo/shell/collection.js:1312:5
@(shell):1:1
2016-11-24T20:07:50.827+0200 E QUERY [thread1] Error: command failed: {
"ok" : 0,
"errmsg" : "the group aggregate field 'From' must be defined as an expression inside an object",
"code" : 15951
} : aggregate failed :
_getErrorWithCode@src/mongo/shell/utils.js:25:13
doassert@src/mongo/shell/assert.js:13:14
assert.commandWorked@src/mongo/shell/assert.js:287:5
DBCollection.prototype.aggregate@src/mongo/shell/collection.js:1312:5
@(shell):1:1
What Did I Do Wrong?
The _id expression specifies the group key. If you specify an _id value of null, or any other constant value, the $group stage returns a single document that aggregates values across all of the input documents. See the Group by Null example.
In MongoDB, each document stored in a collection requires a unique _id field that acts as a primary key.
What you want to achieve - assuming you want to group by from & to - can be done with the following group
:
{"$group": { "_id": {'From': "$headers.From", 'To': "$headers.To"}, "count": {$sum:1}}}
From the reference documentation:
$group
Groups documents by some specified expression and outputs to the next stage a document for each distinct grouping. The output documents contain an _id field which contains the distinct group by key. The output documents can also contain computed fields that hold the values of some accumulator expression grouped by the $group‘s _id field
The accumulator expressions are expressions such as min
, max
(per group), sum
(as you've used), arrays expression (specified by push
and addToSet
) and others.
Specifically, the error message notes that you must use one of the above mentioned expressions as a value for the Form
field.
If you don't like the From
and To
"squeezed" inside _id
, you can later expend it, by adding a $project
stage.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With