0

使用 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">]}
4

4 回答 4

0

这里有几件事是错误的。

  1. 您似乎将Enumerable#group_by与数据库GROUP BY运算符混淆了。
  2. 您认为资源类型的名称来自哪里?它似乎不在资源中。

看起来资源类型的名称在不同的集合中,您必须将 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]] }]
于 2013-04-28T20:40:12.437 回答
0

Old Pro 提到的方法很棒,但比预期的要长一点。我花了一些时间查看grouped_collection_select帮助文档中给出的示例,要点是:“为了保持简单和面向对象的方式,您必须从 ResourceType(一个)遍历到 Resource(很多),而不是相反”。另一种方式会令人困惑,因为我们将处理与 ORM 对象相反的没有关系的自定义嵌套数组。

因此,我想要的输出可以通过 ERB 中的以下 Ruby(单行)代码生成:

<%= field.grouped_collection_select :resource_id, ResourceType.order_by([:name,:asc]), 
    :resources, :name, :id, :title,  :prompt => true %>

..where :resourcesand:name属于 ResourceType 并且:idand:title是 forResource的选项。

希望它也能帮助其他人。

于 2013-04-30T08:11:26.760 回答
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)) %>

希望能帮助到你!享受!

于 2013-05-03T04:05:24.960 回答
-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>]]
    ]
    
  • last对步骤 1 中返回的数组的每一行的方法调用返回一个 Resource 对象数组。

  • first对步骤 1 中返回的数组的每一行的方法调用返回资源类型名称。
  • 对步骤 2 中返回的数组的每一行的andid方法调用返回资源对象的 id 和名称。name
于 2013-04-26T21:06:19.973 回答