我正在使用以下代码从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只是从连接中获取数据库和集合对象。 在fetch方法中,我使用count方法检查是否有结果。由于我得到0,应该有1项,我在gem中将以下代码添加到Cursor类的count方法中:
if response['n'].to_i == 0
require "ruby-debug"
debugger
puts "stop here"
end
(response = @ db.command(command))
在调试器中
@db.command(command)['n'].to_i
返回1.如果我在fetch方法中调用count两次(一次不使用输出),一切都很好。我错过了什么吗?缓冲或缓存问题?然而,这似乎不是确定性的......它只发生在大约50%的运行中。 Mongodb是2.0.2和Ruby 1.9.3p125。
感谢您的帮助!
答案 0 :(得分:0)
我怀疑你在某处有错误,并建议你检查你的游标查询的结果(例如,p collection.find(query).to_a)与集合(例如p collection.find.to_a)。以下适用于Ruby 1.9.3,Mongo 2.0.4,mongo-ruby-driver 1.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
答案 1 :(得分:0)
嗯,意想不到的解决方案:
为了插入测试数据,我在规范
中使用了以下语句collection.insert @hash
insert方法有一个选项:safe,请参阅API。使用默认值(false),mongodb将其存储为异步并继续执行代码。这可能会导致奇怪的行为,如果您之后立即查询它,则该值尚未在数据库中。只需使用
collection.insert @hash, :safe => true