0

私は mongomapper を使用して mongodb で Rails アプリをサポートしており、特定のデータセットの関連付けに対してクエリを実行する必要があります。

たとえば。

クラス ユーザー
  インクルード Mongomapper::Document

  キー:年齢、整数
  多くの:才能
終わり
クラスタレント
  インクルード Mongomapper::Document

  キー:名前、文字列
終わり

31 歳のユーザーを検索する場合は、簡単に実行できます。

User.find_by_age(31)。

しかし、ジャグリングの才能がある 31 歳のユーザーを検索するにはどうすればよいでしょうか?? このようなもの:

User.find_by_age_and_talent(31, "ジャグリング")

mongomapper を使用する必要はありません...直接の mongodb クエリである可能性があります。

4

1 に答える 1

3

モデルにタイプミスがあることに注意してください。MongomapperはMongoMapperである必要があります。これをキャッチして、戸惑いを防いでください。

モデルは個別のドキュメントを指定しているため、検索条件は個別のドキュメントに含まれています。したがって、ドキュメントにまたがる単一のクエリを指定することはできません。これは結合に相当し、MongoDBには結合がありません。そのため、書かれているように、プライマリ結果セットの徹底的なセカンダリクエリで立ち往生しています。

ただし、Talentを埋め込みドキュメントに変更すると、MongoDBで単一のクエリを実行できるため、SQLで必要な結合オーバーヘッドなしで、ストレージとクエリの両方でMongoDBの美しさを活用できます。

いずれかのバージョンを実行するには、次のモデルのインクルードをMongoMapper::DocumentまたはMongoMapper::EmbeddedDocumentに変更するだけです。テストファイルは、変更なしで両方をサポートします。

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

  key :name, String
end

test / unit / 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
于 2012-05-15T20:19:50.183 に答える