Added support for multi-update (available in mongo >= 1.1.3)

This commit is contained in:
Kyle Banker 2009-11-05 16:08:54 -05:00
parent f891b4ece3
commit 867783c665
4 changed files with 33 additions and 13 deletions

View File

@ -235,30 +235,37 @@ module Mongo
# Update a single document in this collection.
#
# :spec :: a hash specifying elements which must be present for
# a document to be updated
# :selector :: a hash specifying elements which must be present for a document to be updated. Note:
# the update command currently updates only the first document matching the
# given selector. If you want all matching documents to be updated, be sure
# to specify :multi => true.
# :document :: a hash specifying the fields to be changed in the
# selected document, or (in the case of an upsert) the document to
# be inserted
# selected document, or (in the case of an upsert) the document to
# be inserted
#
# Options:
# :upsert :: if true, perform an upsert operation
# :multi :: update all documents matching the selector, as opposed to
# just the first matching document. Note: only works in 1.1.3 or later.
# :safe :: if true, check that the update succeeded. OperationFailure
# will be raised on an error. Checking for safety requires an extra
# round-trip to the database
def update(spec, document, options={})
# will be raised on an error. Checking for safety requires an extra
# round-trip to the database
def update(selector, document, options={})
message = ByteBuffer.new
message.put_int(0)
BSON.serialize_cstr(message, "#{@db.name}.#{@name}")
message.put_int(options[:upsert] ? 1 : 0) # 1 if a repsert operation (upsert)
message.put_array(BSON.new.serialize(spec, false).to_a)
update_options = 0
update_options += 1 if options[:upsert]
update_options += 2 if options[:multi]
message.put_int(update_options)
message.put_array(BSON.new.serialize(selector, false).to_a)
message.put_array(BSON.new.serialize(document, false).to_a)
if options[:safe]
@db.send_message_with_safe_check(Mongo::Constants::OP_UPDATE, message,
"db.#{@name}.update(#{spec.inspect}, #{document.inspect})")
"db.#{@name}.update(#{selector.inspect}, #{document.inspect})")
else
@db.send_message_with_operation(Mongo::Constants::OP_UPDATE, message,
"db.#{@name}.update(#{spec.inspect}, #{document.inspect})")
"db.#{@name}.update(#{selector.inspect}, #{document.inspect})")
end
end

View File

@ -465,7 +465,7 @@ module Mongo
end
end
# Note: this method is a stub. Will be completed in an upcoming refactoring.
# Send a message to the database and wait for the response.
def receive_message_with_operation(operation, message, log_message=nil)
message_with_headers = add_message_headers(operation, message).to_s
@logger.debug(" MONGODB #{log_message || message}") if @logger

View File

@ -97,6 +97,20 @@ class TestCollection < Test::Unit::TestCase
assert_equal 1, @@test.find_one(:_id => id2)["x"]
end
if @@version >= "1.1.3"
def test_multi_update
@@test.save("num" => 10)
@@test.save("num" => 10)
@@test.save("num" => 10)
assert_equal 3, @@test.count
@@test.update({"num" => 10}, {"$set" => {"num" => 100}}, :multi => true)
@@test.find.each do |doc|
assert_equal 100, doc["num"]
end
end
end
def test_upsert
@@test.update({"page" => "/"}, {"$inc" => {"count" => 1}}, :upsert => true)
@@test.update({"page" => "/"}, {"$inc" => {"count" => 1}}, :upsert => true)

View File

@ -38,7 +38,6 @@ class CollectionTest < Test::Unit::TestCase
op == 2001 && log.include?("db.books.update")
end
@coll.update({}, {:title => 'Moby Dick'}, :safe => true)
end
should "send safe insert message" do