使用MongoDB时分组选项的最佳方法是什么?
当我尝试这种方法时,我正在使用Mongoid:
<%= field.select :resource_id,
grouped_options_for_select(Resource.all.group_by{"resource_type_id"}.map {|k,m|
[m.first.title, m.first.id] }),:prompt => true %>
它给了我以下错误:
“5177e6a5359f105f89000001”的未定义方法`map':Moped :: BSON :: ObjectId
我正在寻找:
<select>
<optgroup label="RT1"> <!-- RT1 is the name of resource type -->
<option value="5177e6a5359f105f89000001">Res1</option>
</optgroup>
</select>
此外,在控制台中Resource.all.group_by{"resource_type_id"}
的输出是
=> {"resource_type"=>[#<Resource _id: 5177e6a5359f105f89000001,
created_at: 2013-04-24 14:05:25 UTC, updated_at: 2013-04-24 14:54:14 UTC,
title: {"en"=>"Res1"}, slug: {"en"=>"res1"}, content:
{"en"=>"This is the content for First Resource."},
excerpt: {"en"=>"This is the content for First Resource."}, published: true,
resource_type_id: "5177e3ba359f10d345000004">]}
虽然预期结果是
=> {"RT1"=>[#<Resource _id: 5177e6a5359f105f89000001,
created_at: 2013-04-24 14:05:25 UTC, updated_at: 2013-04-24 14:54:14 UTC,
title: {"en"=>"Res1"}, slug: {"en"=>"res1"}, content:
{"en"=>"This is the content for First Resource."},
excerpt: {"en"=>"This is the content for First Resource."}, published: true,
resource_type_id: "5177e3ba359f10d345000004">]}
答案 0 :(得分:0)
这里有几件事是错误的。
GROUP BY
运算符混淆。看起来资源类型的名称位于不同的集合中,您必须分别将ID映射到名称。这是Mongoid的NoSQL部分:您不能简单地加入Resource和ResourceType表。
Resource.all.group_by { |r| r.resource_type_id }
会让你入门,但哈希键将是ID,而不是名称。 (这也会同时将所有资源读入内存,这在很多情况下会出现问题,但由于你在选项列表中显示所有这些资源,我假设列表足够小就可以了。)你'然后需要获取名称映射并替换散列键。类似的东西:
resource_names = {}
ResourceType.each { |rt| resource_names[rt.id] = rt.name }
resource_groups = Resource.all.group_by { |r| r.resource_type_id }
resource_options = Hash[resource_groups.map { |k, v| [resource_names[k] || k, [v.title["en"], v.id]] }]
答案 1 :(得分:0)
Old Pro提到的方法很棒,但比预期的要长。我花了一些时间在grouped_collection_select
helper docs中给出的例子,并且要点是:“为了保持简单和面向对象的方式,你必须从ResourceType(一个)遍历资源(很多)而不是另一个方式周围”。另一种方式会让人感到困惑,因为我们将处理与ORM对象无关的自定义嵌套数组。
因此,我所需的输出可以通过ERB中的以下Ruby(单行)代码生成:
<%= field.grouped_collection_select :resource_id, ResourceType.order_by([:name,:asc]),
:resources, :name, :id, :title, :prompt => true %>
..其中:resources
和:name
属于ResourceType,:id
和:title
属于Resource
选项。
希望它也能帮助别人。
答案 2 :(得分:0)
以下是optgroup的一个示例:
@city_group =
[
["Wisoncin", [["Lake Geneva", "1"],
["Elkhart Lake", "2"]]],
["Michigan", [["Harbor Country", "3"], ["Traverse City", "4"]]],
["Indiana", [["Bloomington", "5"], ["Valparaiso", "6"]]],
["Minnesota", [["Twin Cities",
"7"], ["Bloomington", "8"], ["Stillwater",
"9"]]],
["Florida", [["Sanibel & Captiva", "10"]]],
["Illinois", [["Chicago", "11"],
["Galena", "12"]]],
]
并在您的观看中添加:
<%= select_tag(:brand_id, grouped_options_for_select(@city_group, selected_key = "11", prompt = nil)) %>
希望它有所帮助!请享用!
答案 3 :(得分:-1)
我假设您要按resource_type
而不是resource_type_id
对选项进行分组。
f.grouped_collection_select :resource_id,
Resource.all.group_by(:resource_type).to_a,
:last, :first, :id, :name
<强>解释强>:
Resource.all.group_by(:resource_type).to_a
返回一个数组数组。
[
[ "R1", [<Resource _id 51xx0001>, <Resource _id 51xx0002>]],
[ "R2", [<Resource _id 51xx0003>, <Resource _id 51xx0004>]]
]
在步骤1中返回的数组的每一行上的last
方法调用返回一个Resource对象数组。
first
方法调用,返回资源类型名称。id
和name
方法调用返回资源对象的id和名称。