我是MongoDB的新手。我为我的高尔夫俱乐部做了一个私人项目来分析这一轮。
我对应用程序使用meteorjs,并在命令行上尝试了一些聚合。但我不确定我是否对这项任务有正确的看法
示例文档:
{
"_id" : "2KasYR3ytsaX8YuoT",
"course" : {
"id" : "rHmYJBhRtSt38m68s",
"name" : "CourseXYZ"
},
"player" : {
"id" : "tdaYaSvXJueDq4oTN",
"firstname" : "Just",
"lastname" : "aPlayer"
},
"event" : "Training Day",
"tees" : [
{
"tee" : 1,
"par" : 4,
"fairway" : "straight",
"greenInRegulation" : true,
"putts" : 3,
"strokes" : 5
},
{
"tee" : 2,
"par" : 5,
"fairway" : "right",
"greenInRegulation" : true,
"putts" : 2,
"strokes" : 5
},
{
"tee" : 3,
"par" : 5,
"fairway" : "right",
"greenInRegulation" : false,
"shotType": "bunker",
"putts" : 2,
"strokes" : 5
}
]
}
db.analysis.aggregate([
{$unwind: "$tees"},
{$group: {
_id:"$player.id",
strokes: {$sum: "$tees.strokes"},
par: {$sum: "$tees.par"},
putts: {$sum: "$tees.putts"},
teesPlayed: {$sum:1}
}}
])
{
"_id" : "tdaYaSvXJueDq4oTN",
"strokes" : 15,
"par" : 14,
"putts" : 7,
"teesPlayed" : 3
// here comes what I want to add:
"fairway.straight": 1 // where tees.fairway equals "straight"
"fairway.right": 2 // where tees.fraiway equals "right" (etc.)
"shotType.bunker": 1 // where shotType equals "bunker" etc.
}
最佳答案
根据您的总体需求以及项目的目标MongoDB服务器版本,有几种方法可以实现这一点。
虽然“Meteor”安装和默认项目设置不会“捆绑”MongoDB 3.2实例,但您的项目不必将此类实例用作外部目标。如果这是一个新的项目起步,那么我强烈建议与最新版本的可用工作。甚至可能反对最新的开发版本,这取决于您自己的目标发布周期。用最新鲜的东西工作,你的申请也会很新鲜。
因此,我们从最新的开始。
MongoDB 3.2路-快速
MongoDB 3.2的一大特点是$sum操作方式的改变,这使得它在性能方面非常突出。以前,作为$group的累加器运算符,这将处理单个数值以生成总计。
大的改进隐藏在添加的$project阶段用法中,其中$sum可以直接应用于值数组。即{ "$sum": [1,2,3] }导致6。因此,现在可以使用从源代码生成值数组的任何内容来“嵌套”操作。最值得注意的是:
db.analysis.aggregate([
{ "$group": {
"_id": "$player.id",
"strokes": {
"$sum": {
"$sum": {
"$map": {
"input": "$tees",
"as": "tee",
"in": "$$tee.strokes"
}
}
}
},
"par": {
"$sum": {
"$sum": {
"$map": {
"input": "$tees",
"as": "tee",
"in": "$$tee.par"
}
}
}
},
"putts": {
"$sum": {
"$sum": {
"$map": {
"input": "$tees",
"as": "tee",
"in": "$$tee.putts"
}
}
}
},
"teesPlayed": { "$sum": { "$size": "$tees" } },
"shotsRight": {
"$sum": {
"$size": {
"$filter": {
"input": "$tees",
"as": "tee",
"cond": { "$eq": [ "$$tee.fairway", "right" ] }
}
}
}
},
"shotsStraight": {
"$sum": {
"$size": {
"$filter": {
"input": "$tees",
"as": "tee",
"cond": { "$eq": [ "$$tee.fairway", "straight" ] }
}
}
}
},
"bunkerShot": {
"$sum": {
"$size": {
"$filter": {
"input": "$tees",
"as": "tee",
"cond": { "$eq": [ "$$tee.shotType", "bunker" ] }
}
}
}
}
}}
])
$map技巧来分割每个字段,或者相反,使用$sum对数组进行处理,以仅限于匹配项,并使用$filter对结果字段的匹配长度进行处理,而结果字段更希望“co”UNTS“。$size。db.analysis.aggregate([
{ "$unwind": "$tees" },
{ "$group": {
"_id": "$player.id",
"strokes": { "$sum": "$tees.strokes" },
"par": { "$sum": "$tees.par" },
"putts": { "$sum": "$tees.putts" },
"teedsPlayed": { "$sum": 1 },
"shotsRight": {
"$sum": {
"$cond": [
{ "$eq": [ "$tees.fairway", "right" ] },
1,
0
]
}
},
"shotsStraight": {
"$sum": {
"$cond": [
{ "$eq": [ "$tees.fairway", "straight" ] },
1,
0
]
}
},
"bunkerShot": {
"$sum": {
"$cond": [
{ "$eq": [ "$tees.shotType", "bunker" ] },
1,
0
]
}
}
}}
])
$unwind语句中都有$filter参数中的一些逻辑的地方,该逻辑在这里被转换为"cond"运算符。$cond(then)的参数,或者返回最后一个条件为true(else)的参数。在这种情况下,要么false要么1取决于测试条件是否匹配。这将根据需要为0提供“计数”。{
"_id" : "tdaYaSvXJueDq4oTN",
"strokes" : 15,
"par" : 14,
"putts" : 7,
"teesPlayed" : 3,
"shotsRight" : 2,
"shotsStraight" : 1,
"bunkerShot" : 1
}
$sum的聚合语句,所以一个规则是“键”(除了需要在构造的语句中指定之外)必须在结构的“顶层”中。因此,$group中不允许有“嵌套”结构,因此每个键都有完整的名称。$group后面添加$project阶段:{ "$project": {
"strokes": 1,
"par": 1,
"putts": 1,
"teesPlayed": 1,
"fairway": {
"straight": "$shotsStraight",
"right": "$shotsRight"
},
"shotType": {
"bunker": "$bunkerShot"
}
}}
$group增加了成本,而且成本相当高。它基本上是要为管道中的每个文档添加一个副本,以便处理每个文档中包含的每个数组元素。因此,不仅有加工所有这些生产出来的东西的成本,而且还有一个首先“生产”它们的成本。db.analysis.mapReduce(
function() {
var data = { "strokes": 0 ,"par": 0, "putts": 0, "teesPlayed": 0, "fairway": {} };
this.tees.forEach(function(tee) {
// Increment common values
data.strokes += tee.strokes;
data.par += tee.par;
data.putts += tee.putts;
data.teesPlayed++;
// Do dynamic keys
if (!data.fairway.hasOwnProperty(tee.fairway))
data.fairway[tee.fairway] = 0;
data.fairway[tee.fairway]++;
if (tee.hasOwnProperty('shotType')) {
if (!data.hasOwnProperty('shotType'))
data.shotType = {};
if (!data.shotType.hasOwnProperty(tee.shotType))
data.shotType[tee.shotType] = 0;
data.shotType[tee.shotType]++
}
});
emit(this.player.id,data);
},
function(key,values) {
var data = { "strokes": 0 ,"par": 0, "putts": 0, "teesPlayed": 0, "fairway": {} };
values.forEach(function(value) {
// Common keys
data.strokes += value.strokes;
data.par += value.par;
data.putts += value.putts;
data.teesPlayed += value.teesPlayed;
Object.keys(value.fairway).forEach(function(fairway) {
if (!data.fairway.hasOwnProperty(fairway))
data.fairway[fairway] = 0;
data.fairway[fairway] += value.fairway[fairway];
});
if (value.hasOwnProperty('shotType')) {
if (!data.hasOwnProperty('shotType'))
data.shotType = {};
Object.keys(value.shotType).forEach(function(shotType) {
if (!data.shotType.hasOwnProperty(shotType))
data.shotType[shotType] = 0;
data.shotType[shotType] += value.shotType[shotType];
});
}
});
return data;
},
{ "out": { "inline": 1 } }
)
$unwind,“value”包含所有输出: {
"_id" : "tdaYaSvXJueDq4oTN",
"value" : {
"strokes" : 15,
"par" : 14,
"putts" : 7,
"teesPlayed" : 3,
"fairway" : {
"straight" : 1,
"right" : 2
},
"shotType" : {
"bunker" : 1
}
}
}
_id选项可以是"out",如图所示,您可以将所有结果放入内存(并在16mb bson限制内),也可以是另一个集合,稍后可以从中读取。对于"inline",有一个类似的$out,但这通常是否定的,因为聚合输出可以作为“游标”使用,除非您确实希望它位于集合中。.aggregate()通常会产生最快的结果。另一方面,如果您想“动态地”使用生成的“键”,那么.aggregate()允许逻辑通常是自包含的,而不需要另一个检查过程来生成所需的聚合管道语句。
关于mongodb - MongoDB高级聚合,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/35606546/
不知何故,我似乎无法获得包含我的聚合的响应...使用curl它按预期工作:HBZUMB01$curl-XPOST"http://localhost:9200/contents/_search"-d'{"size":0,"aggs":{"sport_count":{"value_count":{"field":"dwid"}}}}'我收到回复:{"took":4,"timed_out":false,"_shards":{"total":5,"successful":5,"failed":0},"hits":{"total":90,"max_score":0.0,"hits":[]},"a
什么是Linq聚合方法的ruby等价物。它的工作原理是这样的varfactorial=new[]{1,2,3,4,5}.Aggregate((acc,i)=>acc*i);每次将数组序列中的值传递给lambda时,变量acc都会累积。 最佳答案 这在数学以及几乎所有编程语言中通常称为折叠。它是更普遍的变形概念的一个实例。Ruby从Smalltalk中继承了这个特性的名称,它被称为inject:into:(像aCollectioninject:aStartValueinto:aBlock一样使用。)所以,在Ruby中,它称为inj
我目前还在上学,正在上一门关于用C++实现数据结构的类(class)。在业余时间,我喜欢使用“高级”语言(主要是Ruby和一些c#)进行编程。既然这些高级语言为你管理内存,你会用数据结构做什么?我可以理解对队列和堆栈的需求,但是您需要在Ruby中使用二叉树吗?还是2-3-4树?为什么?谢谢。 最佳答案 Sosincethesehigherlevellanguagesmanagethememoryforyou,whatwouldyouusedatastructuresfor?使用数据结构的主要原因与垃圾收集无关。但它是以某种方式有效的
我在使用Arel聚契约(Contract)一查询中的2列时遇到了问题。当我运行它时,在railsdev-server崩溃之前,整个服务器会卡住一分钟。我怀疑是无限循环:)。也许我误解了Arel的整个概念,如果有人能看一下,我将不胜感激。这个查询的预期结果是这样的:[{:user_id=>1,:sum_account_charges=>300,:sum_paid_debts=>1000},...]a_account_charges=Table(:account_charges)a_paid_debts=Table(:paid_debts)a_participants=Table(:exp
我想同时执行多个聚合函数,例如获取按状态分组的最大和最小id:Model.maximum(:id).minimum(:id).group(:status)这行不通(至少对于Rails3.1.1是这样)——你在最小调用时收到一个错误,说它没有在Fixnum上定义。NoMethodError:undefinedmethod`minimum'for22377:Fixnum我可以为它做原始sql-但只是想知道是否有更高级别/Rails选项...谢谢,克里斯 最佳答案 我有一个类似的问题,我在Rails4中使用groupwithpluck解决
我可以在一个Rails应用程序中同时使用MongoDB和PostgreSQL吗?具体来说,我最终会想要使用像MongoHQ这样的东西。到目前为止,我未能在实验中进行这项工作。令我担心的是,MongoDB文档特别指出我必须禁用ActiveRecord。任何建议将不胜感激。 最佳答案 您无需禁用ActiveRecord即可使用MongoDB。查看Mongoid只需将gem加上任何模型与您现有的任何ActiveRecord模型一起添加。您应该注意到MongoHQ只是MongoDB的托管服务,可以与任何对象文档映射器(ODM)一起使用。更多
我必须在mongoid模型中添加几个字段,我知道MongoDB没有迁移,但如果我继续而不删除数据库,使rails完全“重新生成”数据库,它不会显示或使用新的领域!去这里最好的方法是什么?有比删除/重新打开mongodb更软的东西吗?提前致谢卢卡 最佳答案 一般来说,应该可以在运行时用新字段更新旧文档。MongoDB中不需要迁移。您可能想编写rake任务以使用新字段和默认值更新旧文档。您可以通过检查那些默认值为nil的新字段来找到这些文档。更新简单风格:如果您使用默认值定义一个新字段,只要您设置了一个新值,就应该始终使用该值:应用程序
我如何从Ruby代码连接到mongodb? 最佳答案 首先,您必须安装MongoDbgem:geminstallmongo然后运行代码:require'rubygems'#notnecessaryforRuby1.9require'mongo'db=Mongo::Connection.new.db("mydb")#ORdb=Mongo::Connection.new("localhost").db("mydb")#ORdb=Mongo::Connection.new("localhost",27017).db("mydb")
我正在尝试使用聚合框架(使用ruby)并像这样投影日期:db['requests'].aggregate([{"$project"=>{_id:0,method:'$method',user:'$user',year:{'$year'=>'$timestamp'}}}])文档是这样的:{_id:ObjectId("5177d7d7df26358289da7dfd"),timestamp:ISODate("2013-04-12T03:58:05+00:00"),method:"POST",status:"200",inputsize:"874",outputsize:"4981",u
我试图通过在Ruby中进行的查询从MongoDB获取字段的子集,但它似乎不起作用。它不返回任何结果这是ruby代码:coll.find("title"=>'Halo',:fields=>["title","isrc"])#thisdoesn'twork如果我删除字段散列,它会工作,返回包含所有字段的结果coll.find("title"=>'Halo')#thisworks查看mongodb控制台,第一个查询在mongodb服务器上结束,如下所示:{title:"Halo",fields:["title","isrc"]}如果我尝试从mongo客户端控制台进行查询,它会工作,我会得到结