查询mongodb / mongomapper以获取关联数据

时间:2012-05-15 01:47:42

标签: ruby-on-rails mongodb mongomapper

我使用mongomapper来支持使用mongodb的rails应用程序,并且需要查询给定数据集的关联。

例如。

class User
  include Mongomapper::Document

  key :age, Integer
  many :talents
end 
class Talent
  include Mongomapper::Document

  key :name, String
end

现在,如果我想搜索31岁的用户,我可以轻松地进行

User.find_by_age(31).

但我该如何搜索31岁的玩家扮演天赋的用户? 像这样:

User.find_by_age_and_talent(31, "juggling")

不必通过mongomapper ...可能是一个直接的mongodb查询。

1 个答案:

答案 0 :(得分:3)

请注意,你的模型中存在拼写错误,Mongomapper应该是MongoMapper,抓住这个来节省一些困惑。

您的模型指定单独的文档,因此您的搜索条件位于单独的文档中。因此,您不能指定跨越文档的单个查询,这相当于连接,并且MongoDB中没有连接。因此,正如所写的那样,您无法对主要结果集进行详尽的二次查询。

但是,如果您将Talent修改为嵌入式文档,那么您可以在MongoDB中执行单个查询,从而利用MongoDB的优势进行存储和查询,而无需SQL所需的连接开销。

要运行任一版本,只需将以下模型中的include更改为MongoMapper :: Document或MongoMapper :: EmbeddedDocument。测试文件支持两者而无需修改。

class Talent
  #include MongoMapper::Document
  include MongoMapper::EmbeddedDocument

  key :name, String
end

测试/单元/ user_test.rb

require 'test_helper'

class UserTest < ActiveSupport::TestCase
  def setup
    User.delete_all
    Talent.delete_all if Talent.respond_to?(:delete_all)
  end

  test "user talent" do
    if Talent.respond_to?(:create)
      puts "Talent as separate document, not embedded"
      User.create(age: 31, talents: [Talent.create(name: 'juggling')])
      User.create(age: 31, talents: [Talent.create(name: 'singing')])
      User.create(age: 25, talents: [Talent.create(name: 'juggling'), Talent.create(name: 'dancing')])
      assert_equal(3, User.count)
      talent = 'juggling'
      users = User.where(age: 31).select{|user| Talent.where(name: talent).where(user_id: user._id).first}
      assert_equal(1, users.size)
      p users
    else
      puts "Talent as embedded document"
      User.create(age: 31, talents: [Talent.new(name: 'juggling')])
      User.create(age: 31, talents: [Talent.new(name: 'singing')])
      User.create(age: 25, talents: [Talent.new(name: 'juggling'), Talent.new(name: 'dancing')])
      assert_equal(3, User.count)
      talent = 'juggling'
      users = User.where(age: 31).where('talents.name' => talent).to_a
      assert_equal(1, users.size)
      p users
    end
  end
end