我有一个名为'my_emails'的集合,其中存储了电子邮件地址:
[
{ email:"russel@gmail.com"},
{ email:"mickey@yahoo.com"},
{ email:"john@yahoo.com"},
]
我尝试使用前10个主机名...
[
{host: "gmail.com", count: 1000},
{host: "yahoo.com", count: 989}, ...
]
如果我有MySQL,我会做这个查询:
SELECT substr(email,locate('@',email)+1,255) AS host,count(1) AS count
FROM my_emails
WHERE email like '%@%'
GROUP BY substr(email,locate('@',email)+1,255)
ORDER BY count(1) DESC
LIMIT 10
我怎么能用mongodb? 我尝试没有这样的结果:
db.my_emails.aggregate([ { $group : {_id : "$host", count : { $sum : 1 }}}]);
我不知道如何在不向记录添加新属性的情况下制作$ host值
答案 0 :(得分:2)
MongoDB不提供locate
之类的任何运营商,但您可以使用.mapReduce
执行此操作:
db.collection.mapReduce(
function() {
emit(this.email.substr(this.email.indexOf('@') + 1), 1);
},
function(host, count) {
return Array.sum(count) ; },
{ out: "hosts" }
)
然后db.hosts.find().sort({ 'value': -1 }).limit(10)
返回前10名主机名:
{ "_id" : "yahoo.com", "value" : 2 }
{ "_id" : "gmail.com", "value" : 1 }
答案 1 :(得分:0)
另一种解决方法是通过在架构中引入另一个仅包含电子邮件地址的域值的字段来修改数据结构。这可以通过使用 Bulk API 操作进行批量更新来完成,这些操作可以提供更好的写入响应,即有关更新期间实际发生情况的有用信息:
var bulk = db.my_emails.initializeUnorderedBulkOp(),
count = 0;
db.my_emails.find().forEach(function(doc) {
var domain = doc.email.replace(/.*@/, ""),
update = { domain: domain };
bulk.find({ "_id": doc._id }).updateOne({
"$set": update
})
count++;
if (count % 1000 == 0) {
bulk.execute();
bulk = db.my_emails.initializeUnorderedBulkOp();
}
})
if (count % 1000 != 0) { bulk.execute(); }
来自示例的批量更新响应:
BulkWriteResult({
"writeErrors" : [ ],
"writeConcernErrors" : [ ],
"nInserted" : 0,
"nUpserted" : 0,
"nMatched" : 3,
"nModified" : 3,
"nRemoved" : 0,
"upserted" : [ ]
})
在此更新之后,对集合db.my_emails.find().pretty()
的查询将产生:
{
"_id" : ObjectId("561618af645a64b1a70af2c5"),
"email" : "russel@gmail.com",
"domain" : "gmail.com"
}
{
"_id" : ObjectId("561618af645a64b1a70af2c6"),
"email" : "mickey@yahoo.com",
"domain" : "yahoo.com"
}
{
"_id" : ObjectId("561618af645a64b1a70af2c7"),
"email" : "john@yahoo.com",
"domain" : "yahoo.com"
}
现在,拥有域名字段可让 aggregation framework 更轻松地通过 $sum
运算符为您提供主机数量 $group
管道。以下管道操作将返回所需的结果:
db.my_emails.aggregate([
{
"$group": {
"_id": "$domain",
"count": { "$sum": 1 }
}
}
])
<强>输出强>:
{ "_id" : "yahoo.com", "count" : 2 }
{ "_id" : "gmail.com", "count" : 1 }