我正在尝试对来自 mongoDB 集合(使用 nodeJS 驱动程序)的多个字段中的数组中的唯一值进行排序。
一个小数据集:
[{
"_id" : "5c93db3dd0184516406013f7",
"filters" : {
"genres" : [
{
"_id" : "9CXBYc4qP8sqcNMZ5",
"fr" : "Art Abstrait",
"en" : "Abstract Art",
"de" : "Abstrakte Kunst",
"it" : "Arte astratta",
"es" : "Arte Abstracto"
}
],
"subjects" : [
{
"_id" : "3QjL6YSfmuY6NFHGG",
"fr" : "Abstrait",
"en" : "Abstract",
"de" : "Abstrakt",
"it" : "Astratto",
"es" : "Abstracto"
}
],
"type" : {
"_id" : "CYK2WcepkJsy5xXMo",
"fr" : "Gravure au carborundum",
"en" : "Carborundum etching",
"de" : "Carborundum Radierung",
"it" : "Incisione carborandum",
"es" : "Grabado al Carborundum"
}
}
},
{
"_id" : "5c93db3ed0184516406013f8",
"filters" : {
"genres" : [
{
"_id" : "9CXBYc4qP8sqcNMZ5",
"fr" : "Art Abstrait",
"en" : "Abstract Art",
"de" : "Abstrakte Kunst",
"it" : "Arte astratta",
"es" : "Arte Abstracto"
}
],
"subjects" : [
{
"_id" : "3QjL6YSfmuY6NFHGG",
"fr" : "Abstrait",
"en" : "Abstract",
"de" : "Abstrakt",
"it" : "Astratto",
"es" : "Abstracto"
}
],
"type" : {
"_id" : "CYK2WcepkJsy5xXMo",
"fr" : "Gravure au carborundum",
"en" : "Carborundum etching",
"de" : "Carborundum Radierung",
"it" : "Incisione carborandum",
"es" : "Grabado al Carborundum"
}
}
},
{
"_id" : "5c93e19ed018451640601da6",
"filters" : {
"genres" : [
{
"_id" : "9CXBYc4qP8sqcNMZ5",
"fr" : "Art Abstrait",
"en" : "Abstract Art",
"de" : "Abstrakte Kunst",
"it" : "Arte astratta",
"es" : "Arte Abstracto"
}
],
"subjects" : [
{
"_id" : "3QjL6YSfmuY6NFHGG",
"fr" : "Abstrait",
"en" : "Abstract",
"de" : "Abstrakt",
"it" : "Astratto",
"es" : "Abstracto"
}
],
"type" : {
"_id" : "KfGWEHL2pAto8nfze",
"fr" : "Gravure",
"en" : "Etching",
"de" : "Radierung",
"it" : "Incisione",
"es" : "Grabado"
}
}
}]
我的查询结果(lang = 'en'):
{
"subjects": [
{
"_id": "3QjL6YSfmuY6NFHGG",
"fr": "Abstrait",
"en": "Abstract",
"de": "Abstrakt",
"it": "Astratto",
"es": "Abstracto"
},
{
"_id": "3QjL6YSfmuY6NFHGG",
"fr": "Abstrait",
"en": "Abstract",
"de": "Abstrakt",
"it": "Astratto",
"es": "Abstracto"
}
],
"genres": [
{
"_id": "9CXBYc4qP8sqcNMZ5",
"fr": "Art Abstrait",
"en": "Abstract Art",
"de": "Abstrakte Kunst",
"it": "Arte astratta",
"es": "Arte Abstracto"
},
{
"_id": "9CXBYc4qP8sqcNMZ5",
"fr": "Art Abstrait",
"en": "Abstract Art",
"de": "Abstrakte Kunst",
"it": "Arte astratta",
"es": "Arte Abstracto"
}
],
"types": [
{
"_id": "CYK2WcepkJsy5xXMo",
"fr": "Gravure au carborundum",
"en": "Carborundum etching",
"de": "Carborundum Radierung",
"it": "Incisione carborandum",
"es": "Grabado al Carborundum"
},
{
"_id": "KfGWEHL2pAto8nfze",
"fr": "Gravure",
"en": "Etching",
"de": "Radierung",
"it": "Incisione",
"es": "Grabado"
}
]
}
聚合管道:
[
{ $unwind: '$filters.subjects' },
{ $unwind: '$filters.genres' },
{ $group: {
_id: null,
subjects: { $addToSet: '$filters.subjects' },
types: { $addToSet: '$filters.type' },
genres: { $addToSet: '$filters.genres' },
}},
{ $unwind: '$subjects' },
{ $unwind: '$genres' },
{ $unwind: '$types' },
{ $sort: {
[`subjects.${lang}`]: 1,
[`types.${lang}`]: 1,
[`genres.${lang}`]: 1,
}},
{ $group: {
_id: null,
subjects: { $push: '$subjects' },
types: { $push: '$types' },
genres: { $push: '$genres' },
}},
{ $project: {
_id: false,
subjects: '$subjects',
types: '$types',
genres: '$genres'
}}
]
而不是像这样获取唯一值的排序数组:
[A, B, C, D, ...]
我得到具有非唯一值的排序数组,如下所示:
[A, A, A, B, B, B, C, C, C, D, D, D, ...]
使 $addToSet 分组无用。
知道我错了什么吗?
最佳答案
您遇到的问题是每个 $unwind 都将使用您正在展开的数组中的单个数组元素创建文档的副本。你有以下内容:
...
{ $unwind: '$subjects' },
{ $unwind: '$genres' },
{ $unwind: '$types' },
...
因此,首先要展开 subjects,它会为 subjects 中的每个元素生成一个文档,我们将其称为 subject。因此,我们为每个 subject 都有一个文档,它们本身包含数组 genres 和 types。接下来展开 genres 时,每个 subject 文档都会展开以包含来自 genres 的元素 genre。这会使用每个 subject 的 genres.length 副本——也就是说,每个 subject 都根据数组中有多少 genres 进行复制.展开 types 时会发生类似的情况。
简而言之,您在每次调用 $unwind 时都会复制您的数据。
用一个更简单的例子来说明:
// Doc:
{
ints: [1, 2],
alpha: ['a', 'b', 'c']
}
// Pipeline:
[
{ $unwind: "$ints" },
{ $unwind: "$alpha" }
]
// After unwinding "ints":
[
{ ints: 1, alpha: ['a', 'b', 'c'] },
{ ints: 2, alpha: ['a', 'b', 'c'] }
]
// After unwinding "alpha":
[
{ ints: 1, alpha: 'a' },
{ ints: 1, alpha: 'b' },
{ ints: 1, alpha: 'c' },
{ ints: 2, alpha: 'a' },
{ ints: 2, alpha: 'b' },
{ ints: 2, alpha: 'c' }
]
// Result: 3 duplicates of each value in "ints", 2 duplicates of each value in "alpha".
为了解决这个问题,我立即想到了几个选项:
1. 你可以$unwind一个数组,$sort它,$group结果到$push元素返回数组,对每个数组单独重复,一次一个。请注意,您需要使用 $first 运算符在分组时仅获取每个重复数组的一个副本。
2. 您可以将最后一个 $group 管道阶段更改为使用 $addToSet 而不是 $push 操作。
可能还有其他选项可供您使用,但以上任一选项都足以快速解决问题。
关于mongoDB 聚合 : $addToSet then $sort,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/56409219/
我已经搜索过这个问题的答案,但没有成功,有一个类似的问题,但答案在这种情况下不起作用,它按数字项目排序。SimilarQuestion-Thatdidnotwork我正在尝试使用ruby的sort_by对一个项目进行降序排序和另一个升序排序。我只能找到一个。代码如下:#PrimarysortLastNameDescending,withtiesbrokenbysortingAreaofinterest.people=people.sort_by{|a|[a.last_name,a.area_interest]}任何指导肯定会有所帮助。示例数据:输入罗素,逻辑欧拉,图论伽罗瓦,抽象代
不知何故,我似乎无法获得包含我的聚合的响应...使用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
我需要按照作为搜索参数传入的准确顺序查找记录。例如,我有一个字符串:item_list="23,12,54,45"通过以下查询,我按“item_list”的asc顺序获取记录-“12,23,45,54”。Inventory.find(item_list.split(","))如何修改上述查询,使其以与“item_list”相同的顺序返回记录。谢谢。 最佳答案 试试这个,虽然它可能只适用于MySQL:Inventory.where("idIN(#{item_list})").order("find_in_set(id,'#{item_
我想按数据库表列“plays”对其进行排序/排序(按我想要的方式降序或升序)我完全糊涂了。刚刚找到了select而不是collection_select的解决方案?我的一些代码不知道如何排序/排序数据库表中还有一些列,如“plays”、“goals”... 最佳答案 只需将实际排序的集合传递给collection_select助手:collection_select(:post,:author_id,Author.order('created_atDESC'),:id,:name_with_initial,:prompt=>true
我在使用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
ActiveAdmin似乎还不支持多列排序(即将多个值传递给config.sortable选项)。我看到一个老猴子补丁here但它似乎不适用于我的版本(来自Github的1.0.0.pre)。有没有办法在最新的ActiveAdmin版本上获得多个可排序的列? 最佳答案 这也是一个猴子补丁:在config/initializers或lib文件夹中创建一个新文件:multiple_columns_sorting.rbmoduleActiveAdminclassResourceController重启服务器。现在您可以使用由"_and_"
Dir.glob("*.txt"){|f|pf}打印文件名。Dir.glob("*.txt").sort{|f|pf}因ArgumentError失败。Dir.glob("*.txt").sort.each{|f|pf}按字母顺序打印文件名。为什么第二个失败了?更好的是,为什么第一个工作,有或没有.each?Dir.glob和Dir.glob.sort都是数组。Dir.glob.methods==Dir.glob.sort.methods。(受AlphabetizeresultsofDir.glob启发。不是Dir.globwithsortissue的副本,因为“第三个”已经回答了那个
我想同时执行多个聚合函数,例如获取按状态分组的最大和最小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)一起使用。更多