ruby-on-rails – Mongoid:按嵌套子值排序

class Box
  embeds_many :things
  after_init :add_default_things

  def add_default_things
    self.things.build(title: "Socks", value: 2)
    self.things.build(title: "Ring", value: 1)
  end
end

class Thing
  field :title
  field :value, type: Integer
end

所有的盒子都有一些默认的东西:袜子和戒指.每个人都可以将这个或另一个东西添加到一个盒子里.所以现在我需要按袜子的数量订购所有盒子:

Box.order_by(:thing_with_title_socks.value.desc) # ???

最佳答案 我不擅长ruby,所以我将尝试用java术语来解释它.问题是你如何设计数据.例如,你有n个Box类,每个类都有一个项目列表:

public class Box {
  public List<Item> items;
}

public class Item {
  public String name;
  public int value;
}

要对这个类中的所有框进行排序以获取特定的项目值,您需要循环遍历所有项目中的所有项目.所以我会改变我的代码来更有效地做到这一点:

public class Box {
  public Map<Integer, Item> items;
}

public class Item {
  public int id;
  public String name;
  public int value;
}

这样我会检查项目是否存在于框中;访问具有O(1)复杂度的items值,我不会错误地在我的盒子中放入2个不同的袜子包,这会导致错误(哪一个会排序?).

您当前的数据结构如下:

{
  things : [ {"name" : "socks", "value" : 2} , {"name" : "ring", "value" : 5} ]
}

但是如果您要对“已知”对象(如戒指或袜子)进行排序/直接访问(在查询中使用),那么您的数据应如下所示:

{
  things : { "socks": 2, "ring" : 5 }
}

如果你有额外的信息附加到这些项目,他们也可以看起来像:

{
  things : { "S01" : { "name" : "super socks", "value" : 1 }, "S02" : { "name" : "different socks", "value" : 2} }
}

这样您就可以直接访问框中的项目.

希望这会有所帮助.

编辑:我认为这很明显但只是为了清楚地说明:除非你知道确切的位置,否则你无法有效地查询“列出的”子数据. (你总是可以使用map / reduce)

点赞