我有这三个 MongoDB 文档:
{
"_id" : ObjectId("571094afc2bcfe430ddd0815"),
"name" : "Barry",
"surname" : "Allen",
"address" : [
{
"street" : "Red",
"number" : NumberInt(66),
"city" : "Central City"
},
{
"street" : "Yellow",
"number" : NumberInt(7),
"city" : "Gotham City"
}
]
}
{
"_id" : ObjectId("57109504c2bcfe430ddd0816"),
"name" : "Oliver",
"surname" : "Queen",
"address" : {
"street" : "Green",
"number" : NumberInt(66),
"city" : "Star City"
}
}
{
"_id" : ObjectId("5710953ac2bcfe430ddd0817"),
"name" : "Tudof",
"surname" : "Unknown",
"address" : "homeless"
}
address 字段是第一个文档中的对象的 Array、第二个文档中的 Object 和 String在第三。
我的目标是找出我的集合中有多少文档包含字段 address.street。在这种情况下,正确的计数是 1,但通过我的查询,我得到了两个:
db.coll.find({"address.street":{"$exists":1}}).count()
我也尝试过 map/reduce。它有效,但速度较慢;所以如果可能的话,我会避免它。
最佳答案
这里的区别在于 .count() 操作在返回字段存在的“文档”计数时实际上是“正确的”。因此,一般考虑可分解为:
那么最有效的方法是排除那些“街道”是“地址”属性的文档作为“数组”,然后只需使用查找 0 的点符号属性> 排除项中不存在的索引:
db.coll.find({
"address.street": { "$exists": true },
"address.0": { "$exists": false }
}).count()
在这两种情况下,$exists 都作为 native 编码的运算符测试执行正确且高效的工作。
如果您实际询问的是“字段计数”,其中一些“文档”包含数组条目,其中该“字段”可能出现多次。
为此,您需要您提到的聚合框架或 mapReduce。 MapReduce 使用基于 JavaScript 的处理,因此比 .count() 操作要慢得多。聚合框架还需要计算并且“将”比 .count() 慢,但不会像 mapReduce 那么多。
在 MongoDB 3.2 中,您可以通过 $sum 的扩展功能获得一些帮助处理一组值以及作为分组累加器。这里的另一个助手是 $isArray允许通过 $map 使用不同的处理方法当数据实际上是“一个数组”时:
db.coll.aggregate([
{ "$group": {
"_id": null,
"count": {
"$sum": {
"$sum": {
"$cond": {
"if": { "$isArray": "$address" },
"then": {
"$map": {
"input": "$address",
"as": "el",
"in": {
"$cond": {
"if": { "$ifNull": [ "$$el.street", false ] },
"then": 1,
"else": 0
}
}
}
},
"else": {
"$cond": {
"if": { "$ifNull": [ "$address.street", false ] },
"then": 1,
"else": 0
}
}
}
}
}
}
}}
])
早期版本依赖于更多的条件处理,以便以不同方式处理数组和非数组数据,通常需要 $unwind处理数组条目。
通过 $map 转置数组使用 MongoDB 2.6:
db.coll.aggregate([
{ "$project": {
"address": {
"$cond": {
"if": { "$ifNull": [ "$address.0", false ] },
"then": "$address",
"else": {
"$map": {
"input": ["A"],
"as": "el",
"in": "$address"
}
}
}
}
}},
{ "$unwind": "$address" },
{ "$group": {
"_id": null,
"count": {
"$sum": {
"$cond": {
"if": { "$ifNull": [ "$address.street", false ] },
"then": 1,
"else": 0
}
}
}
}}
])
或者使用 MongoDB 2.2 或 2.4 提供条件选择:
db.coll.aggregate([
{ "$group": {
"_id": "$_id",
"address": {
"$first": {
"$cond": [
{ "$ifNull": [ "$address.0", false ] },
"$address",
{ "$const": [null] }
]
}
},
"other": {
"$push": {
"$cond": [
{ "$ifNull": [ "$address.0", false ] },
null,
"$address"
]
}
},
"has": {
"$first": {
"$cond": [
{ "$ifNull": [ "$address.0", false ] },
1,
0
]
}
}
}},
{ "$unwind": "$address" },
{ "$unwind": "$other" },
{ "$group": {
"_id": null,
"count": {
"$sum": {
"$cond": [
{ "$eq": [ "$has", 1 ] },
{ "$cond": [
{ "$ifNull": [ "$address.street", false ] },
1,
0
]},
{ "$cond": [
{ "$ifNull": [ "$other.street", false ] },
1,
0
]}
]
}
}
}}
])
所以后一种形式“应该”比 mapReduce 表现好一点,但可能不会好很多。
在所有情况下,逻辑都归结为使用 $ifNull作为聚合框架的 $exists 的“逻辑”形式。与 $cond 配对,当属性实际存在时得到一个“truthfull”结果,不存在时返回一个false值。这决定了是1还是0分别通过$sum返回到整体累加中。 .
理想情况下,您拥有可以在单个 $group 中执行此操作的现代版本管道阶段,否则您需要更长的路径。
关于mongodb - 计算有多少文档包含一个字段,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/36645838/
使用带有Rails插件的vim,您可以创建一个迁移文件,然后一次性打开该文件吗?textmate也可以这样吗? 最佳答案 你可以使用rails.vim然后做类似的事情::Rgeneratemigratonadd_foo_to_bar插件将打开迁移生成的文件,这正是您想要的。我不能代表textmate。 关于ruby-使用VimRails,您可以创建一个新的迁移文件并一次性打开它吗?,我们在StackOverflow上找到一个类似的问题: https://sta
我需要从一个View访问多个模型。以前,我的links_controller仅用于提供以不同方式排序的链接资源。现在我想包括一个部分(我假设)显示按分数排序的顶级用户(@users=User.all.sort_by(&:score))我知道我可以将此代码插入每个链接操作并从View访问它,但这似乎不是“ruby方式”,我将需要在不久的将来访问更多模型。这可能会变得很脏,是否有针对这种情况的任何技术?注意事项:我认为我的应用程序正朝着单一格式和动态页面内容的方向发展,本质上是一个典型的网络应用程序。我知道before_filter但考虑到我希望应用程序进入的方向,这似乎很麻烦。最终从任何
我想要做的是有2个不同的Controller,client和test_client。客户端Controller已经构建,我想创建一个test_clientController,我可以使用它来玩弄客户端的UI并根据需要进行调整。我主要是想绕过我在客户端中内置的验证及其对加载数据的管理Controller的依赖。所以我希望test_clientController加载示例数据集,然后呈现客户端Controller的索引View,以便我可以调整客户端UI。就是这样。我在test_clients索引方法中试过这个:classTestClientdefindexrender:template=>
为了将Cucumber用于命令行脚本,我按照提供的说明安装了arubagem。它在我的Gemfile中,我可以验证是否安装了正确的版本并且我已经包含了require'aruba/cucumber'在'features/env.rb'中为了确保它能正常工作,我写了以下场景:@announceScenario:Testingcucumber/arubaGivenablankslateThentheoutputfrom"ls-la"shouldcontain"drw"假设事情应该失败。它确实失败了,但失败的原因是错误的:@announceScenario:Testingcucumber/ar
我有一个表单,其中有很多字段取自数组(而不是模型或对象)。我如何验证这些字段的存在?solve_problem_pathdo|f|%>... 最佳答案 创建一个简单的类来包装请求参数并使用ActiveModel::Validations。#definedsomewhere,atthesimplest:require'ostruct'classSolvetrue#youcouldevencheckthesolutionwithavalidatorvalidatedoerrors.add(:base,"WRONG!!!")unlesss
我想向我的Controller传递一个参数,它是一个简单的复选框,但我不知道如何在模型的form_for中引入它,这是我的观点:{:id=>'go_finance'}do|f|%>Transferirde:para:Entrada:"input",:placeholder=>"Quantofoiganho?"%>Saída:"output",:placeholder=>"Quantofoigasto?"%>Nota:我想做一个额外的复选框,但我该怎么做,模型中没有一个对象,而是一个要检查的对象,以便在Controller中创建一个ifelse,如果没有检查,请帮助我,非常感谢,谢谢
这里是Ruby新手。完成一些练习后碰壁了。练习:计算一系列成绩的字母等级创建一个方法get_grade来接受测试分数数组。数组中的每个分数应介于0和100之间,其中100是最大分数。计算平均分并将字母等级作为字符串返回,即“A”、“B”、“C”、“D”、“E”或“F”。我一直返回错误:avg.rb:1:syntaxerror,unexpectedtLBRACK,expecting')'defget_grade([100,90,80])^avg.rb:1:syntaxerror,unexpected')',expecting$end这是我目前所拥有的。我想坚持使用下面的方法或.join,
如果您尝试在Ruby中的nil对象上调用方法,则会出现NoMethodError异常并显示消息:"undefinedmethod‘...’fornil:NilClass"然而,有一个tryRails中的方法,如果它被发送到一个nil对象,它只返回nil:require'rubygems'require'active_support/all'nil.try(:nonexisting_method)#noNoMethodErrorexceptionanymore那么try如何在内部工作以防止该异常? 最佳答案 像Ruby中的所有其他对象
关闭。这个问题需要detailsorclarity.它目前不接受答案。想改进这个问题吗?通过editingthispost添加细节并澄清问题.关闭8年前。Improvethisquestion为什么SecureRandom.uuid创建一个唯一的字符串?SecureRandom.uuid#=>"35cb4e30-54e1-49f9-b5ce-4134799eb2c0"SecureRandom.uuid方法创建的字符串从不重复?
我知道我可以指定某些字段来使用pluck查询数据库。ids=Item.where('due_at但是我想知道,是否有一种方法可以指定我想避免从数据库查询的某些字段。某种反拔?posts=Post.where(published:true).do_not_lookup(:enormous_field) 最佳答案 Model#attribute_names应该返回列/属性数组。您可以排除其中一些并传递给pluck或select方法。像这样:posts=Post.where(published:true).select(Post.attr