{
_id: 42,
foo: {
bar: [1, 2, 3, 3, 4, 5, 5]
}
}
我想“从 foo.bar 中删除所有 $lt: 4 的条目以及与 $ 匹配的第一个匹配条目当量:5”。 重要:$eq 部分只能删除一个单个条目!
我有一个可行的解决方案,它使用 3 个更新查询,但这对于这个简单的任务来说太多了。不过,这是我到目前为止所做的:
1. 找到匹配$eq: 5 和$unset 的第一个条目。 (如您所知:$unset 不会删除它。它只是将其设置为 null):
update(
{ 'foo.bar': 5 },
{ $unset: { 'foo.bar.$': 1 } }
)
2. $pull 所有条目 $eq: null,所以前 5 真的不见了:
update(
{},
{ $pull: { 'foo.bar': null } }
)
3. $pull 所有条目 $lt: 4:
update(
{},
{ $pull: { 'foo.bar': { $lt: 4 } } }
)
{
_id: 42,
foo: {
bar: [4, 5]
}
}
扩展查询1.,这样它将$unset 条目$lt: 4 和一个条目 $eq: 5。之后我们可以执行查询2.,不需要查询3.。
扩展查询 2. 到 $pull 所有匹配 $or: [{$lt: 4}, {$eq: 5} ]。那么就不需要查询3.。
将查询2. 扩展到$pull 所有$not: { $gte: 4 } 。此表达式应匹配 $lt: 4 和 $eq: null。
我已经尝试实现这些查询,但有时它会提示查询语法,有时查询确实执行了但什么也没删除。
如果有人对此有可行的解决方案,那就太好了。
最佳答案
不确定我是否理解您的全部意思,但是要“批量”更新文档,除了原始 $pull 之外,您始终可以采用这种方法。并添加一些“检测”您需要从中删除“重复”5 的文档:
// Remove less than four first
db.collection.update({},{ "$pull": { "foo.bar": { "$lt": 4 } } },{ "multi": true });
// Initialize Bulk
var bulk = db.collection.initializeOrderdBulkOp(),
count = 0;
// Detect and cycle documents with duplicate five to be removed
db.collection.aggregate([
// Project a "reduced" array and calculate if the same size as orig
{ "$project": {
"foo.bar": { "$setUnion": [ "$foo.bar", [] ] },
"same": { "$eq": [
{ "$size": { "$setUnion": [ "$foo.bar", [] ] } },
{ "$size": "$foo.bar" }
] }
}},
// Filter the results that were unchanged
{ "$match": { "same": true } }
]).forEach(function(doc) {
bulk.find({ "_id": doc._id })
.updateOne({ "$set": { "foo.bar": doc.foo.bar.sort() } });
count++;
// Execute per 1000 processed and re-init
if ( count % 1000 == 0 ) {
bulk.execute();
bulk = db.collection.initializeOrderdBulkOp();
}
});
// Clean up any batched
if ( count % 1000 != 0 )
bulk.execute();
这将删除小于“4”的任何内容以及所有从“设置”长度的差异中检测到“重复”的重复项。
如果您只想将 5 的值作为重复值删除,您可以采用类似的逻辑方法来检测和修改,只是不使用“设置运算符”来删除任何“重复”的内容它是一个有效的“集合”。
无论如何,某些检测策略会比迭代更新更好,直到“除了一个”值都消失。
当然你可以稍微简化你的语句并删除一个更新操作,这不是很好,因为 $pull 不允许在查询中使用 $or 条件,但是如果这适用,我希望你能理解:
db.collection.update(
{ "foo.bar": 5 },
{ "$unset": { "foo.bar.$": 1 } },
{ "multi": true }
); // same approach
// So include all the values "less than four"
db.collection.update(
{ "foo.bar": { "$in": [1,2,3,null] } },
{ "$pull": { "foo.bar": { "$in": [1,2,3,null] } }},
{ "multi": true }
);
它的处理要少一些,但当然那些需要是精确的整数值。否则坚持你正在做的三个更新。比在代码中循环更好。
作为引用,不幸的是,“更好”的语法不起作用应该是这样的:
db.collection.update(
{
"$or": [
{ "foo.bar": { "$lt": 4 } },
{ "foo.bar": null }
]
},
{
"$pull": {
"$or": [
{ "foo.bar": { "$lt": 4 } },
{ "foo.bar": null }
]
}
},
{ "multi": true }
);
可能值得一个 JIRA 问题,但我怀疑主要是因为数组元素不是紧跟在 $pull 之后的“第一个”参数。
关于arrays - MongoDB:$pull/$unset 有多个条件,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/31087237/
Rails2.3可以选择随时使用RouteSet#add_configuration_file添加更多路由。是否可以在Rails3项目中做同样的事情? 最佳答案 在config/application.rb中:config.paths.config.routes在Rails3.2(也可能是Rails3.1)中,使用:config.paths["config/routes"] 关于ruby-on-rails-Rails3中的多个路由文件,我们在StackOverflow上找到一个类似的问题
我怎样才能完成http://php.net/manual/en/function.call-user-func-array.php在ruby中?所以我可以这样做:classAppdeffoo(a,b)putsa+benddefbarargs=[1,2]App.send(:foo,args)#doesn'tworkApp.send(:foo,args[0],args[1])#doeswork,butdoesnotscaleendend 最佳答案 尝试分解数组App.send(:foo,*args)
我有多个ActiveRecord子类Item的实例数组,我需要根据最早的事件循环打印。在这种情况下,我需要打印付款和维护日期,如下所示:ItemAmaintenancerequiredin5daysItemBpaymentrequiredin6daysItemApaymentrequiredin7daysItemBmaintenancerequiredin8days我目前有两个查询,用于查找maintenance和payment项目(非排他性查询),并输出如下内容:paymentrequiredin...maintenancerequiredin...有什么方法可以改善上述(丑陋的)代
我需要从一个View访问多个模型。以前,我的links_controller仅用于提供以不同方式排序的链接资源。现在我想包括一个部分(我假设)显示按分数排序的顶级用户(@users=User.all.sort_by(&:score))我知道我可以将此代码插入每个链接操作并从View访问它,但这似乎不是“ruby方式”,我将需要在不久的将来访问更多模型。这可能会变得很脏,是否有针对这种情况的任何技术?注意事项:我认为我的应用程序正朝着单一格式和动态页面内容的方向发展,本质上是一个典型的网络应用程序。我知道before_filter但考虑到我希望应用程序进入的方向,这似乎很麻烦。最终从任何
通过rubykoans.com,我在about_array_assignment.rb中遇到了这两段代码你怎么知道第一个是非并行赋值,第二个是一个变量的并行赋值?在我看来,除了命名差异之外,代码几乎完全相同。4deftest_non_parallel_assignment5names=["John","Smith"]6assert_equal["John","Smith"],names7end45deftest_parallel_assignment_with_one_variable46first_name,=["John","Smith"]47assert_equal'John
我有一个具有一些属性的模型:attr1、attr2和attr3。我需要在不执行回调和验证的情况下更新此属性。我找到了update_column方法,但我想同时更新三个属性。我需要这样的东西:update_columns({attr1:val1,attr2:val2,attr3:val3})代替update_column(attr1,val1)update_column(attr2,val2)update_column(attr3,val3) 最佳答案 您可以使用update_columns(attr1:val1,attr2:val2
我正在尝试修改当前依赖于定义为activeresource的gem:s.add_dependency"activeresource","~>3.0"为了让gem与Rails4一起工作,我需要扩展依赖关系以与activeresource的版本3或4一起工作。我不想简单地添加以下内容,因为它可能会在以后引起问题:s.add_dependency"activeresource",">=3.0"有没有办法指定可接受版本的列表?~>3.0还是~>4.0? 最佳答案 根据thedocumentation,如果你想要3到4之间的所有版本,你可以这
我有一个用户工厂。我希望默认情况下确认用户。但是鉴于unconfirmed特征,我不希望它们被确认。虽然我有一个基于实现细节而不是抽象的工作实现,但我想知道如何正确地做到这一点。factory:userdoafter(:create)do|user,evaluator|#unwantedimplementationdetailshereunlessFactoryGirl.factories[:user].defined_traits.map(&:name).include?(:unconfirmed)user.confirm!endendtrait:unconfirmeddoenden
我有一些代码在几个不同的位置之一运行:作为具有调试输出的命令行工具,作为不接受任何输出的更大程序的一部分,以及在Rails环境中。有时我需要根据代码的位置对代码进行细微的更改,我意识到以下样式似乎可行:print"Testingnestedfunctionsdefined\n"CLI=trueifCLIdeftest_printprint"CommandLineVersion\n"endelsedeftest_printprint"ReleaseVersion\n"endendtest_print()这导致:TestingnestedfunctionsdefinedCommandLin
我有一个只接受一个参数的方法:defmy_method(number)end如果使用number调用方法,我该如何引发错误??通常,我如何定义方法参数的条件?比如我想在调用的时候报错:my_method(1) 最佳答案 您可以添加guard在函数的开头,如果参数无效则引发异常。例如:defmy_method(number)failArgumentError,"Inputshouldbegreaterthanorequalto2"ifnumbereputse.messageend#=>Inputshouldbegreaterthano