0

私はmongoから何かをフェッチするために次のコードを使用しています:

class BlockingMongoFetcher
  include MongoConfig

  def initialize
    configure
    @connection = Mongo::Connection.new(@server, @port)
    @collection = init_collection(@connection)
  end

  def fetch(value)
    mongo_cursor = @collection.find({ KEY => value.to_s })

    if mongo_cursor.count == 0
      # do stuff
      return nil
    end

    if mongo_cursor.count > 1
      # do stuff
    end

    mongo_cursor.first
  end
end

init_collectionは、接続からdbとコレクションオブジェクトを取得するだけです。fetchメソッドでは、countメソッドを使用して結果があるかどうかを確認しています。アイテムが1つあるはずの0を取得したので、gem内の次のコードをCursorクラスのcountメソッドに追加しました。

if response['n'].to_i == 0
  require "ruby-debug"
  debugger
  puts "stop here"
end

(応答= @ db.command(コマンド))

デバッガー内

@db.command(command)['n'].to_i

1を返します。fetchメソッドでcountを2回(出力を使用せずに1回)呼び出すと、すべて問題ありません。私は何かが足りないのですか?バッファまたはキャッシュの問題?ただし、これは決定論的ではないようです...実行の約50%でのみ発生します。Mongodbは2.0.2、Ruby1.9.3p125です。

ご協力いただきありがとうございます!

4

2 に答える 2

0

どこかにエラーがあると思われるので、カーソルクエリ(例:p collection.find(query).to_a)とコレクション(例:p collection.find.to_a)の結果を確認することをお勧めします。以下は、Ruby 1.9.3、Mongo 2.0.4、mongo-ruby-driver1.6.2で動作します。それがお役に立てば幸いです。おそらく、それが自分にも役立つことを確認し、ソリューションに収束できることを確認できます。

MongoConfig.rb

require "mongo"

KEY = 'my_key'

module MongoConfig
  SERVER = 'localhost'
  PORT = Mongo::Connection::DEFAULT_PORT
  DB = 'my_db'
  COLLECTION = 'my_collection'

  attr_accessor :db, :collection

  def configure
    @server = SERVER
    @port = PORT
  end

  def init_collection(connection)
    @db = connection[MongoConfig::DB]
    @collection = @db[MongoConfig::COLLECTION]
    return @collection
  end

end

blocking_mongo_fetcher_test.rb

$LOAD_PATH.unshift(File.expand_path("..", __FILE__))

require "test-unit"
require "MongoConfig"
require "BlockingMongoFetcher"

class BlockingMongoFetcherTest < Test::Unit::TestCase

  def setup
    clear_collection
  end

  def clear_collection
    Mongo::Connection.new[MongoConfig::DB][MongoConfig::COLLECTION].remove
  end

  def count_various_ways_and_cursor_twice_test
    value = 'my name'
    query = {KEY => value}
    count_command = {'count' => MongoConfig::COLLECTION, 'query' => { KEY => value} }
    fetcher = BlockingMongoFetcher.new

    assert_equal(0, fetcher.collection.count) # collection count
    assert_equal(0, fetcher.collection.find(query).count) # cursor count
    assert_equal(0, fetcher.db.command(count_command)['n'].to_i) # db command count
    assert_nil(fetcher.fetch(value))

    fetcher.collection.insert({KEY => value})
    fetcher.collection.insert({KEY => 'x'})

    assert_equal(2, fetcher.collection.count) # collection count
    assert_equal(1, fetcher.collection.find(query).count) # cursor count
    assert_equal(1, fetcher.db.command(count_command)['n'].to_i) # db command count
    assert_equal(value, fetcher.fetch(value)[KEY])

    cursor = fetcher.collection.find(query)
    assert_equal(1, cursor.count) # check once
    assert_equal(1, cursor.count) # check twice
  end

  test "basic test" do
    count_various_ways_and_cursor_twice_test
  end

  test "repeated test" do
    100.times do
      clear_collection
      count_various_ways_and_cursor_twice_test
    end
  end

end
于 2012-04-23T17:19:32.367 に答える
0

うーん、予期しない解決策:

テストデータを挿入するために、仕様内で次のステートメントを使用しました

collection.insert @hash

insertメソッドにはオプション:safeがあります。APIを参照してください。デフォルト(false)の場合、mongodbはそれを非同期で保存し、コードの実行を続行します。後ですぐにクエリを実行すると、値がまだデータベースにないなど、奇妙な動作が発生する可能性があります。使用するだけ

collection.insert @hash, :safe => true
于 2012-05-14T14:51:03.270 に答える