Lets say I have a document Person
, and I wish to add Tags
to this document.
So I would like a document to look like
{ "_id" : 5,
"tags" : ["Music", "Baseball", "Skiing"]
}
Everytime a person chooses an interest, I would like to append it to the tags
list.
Here is my attempt:
require 'mongo'
client = Mongo::Connection.new
db = client['some_app']
coll = db['persons']
coll.update({_id: 5}, {"$push" => {tags: "PS4"}}, {upsert: true})
If I run this I get an exception:
/usr/local/rvm/gems/ruby-2.1.2/gems/bson-1.10.2/lib/bson/bson_c.rb:20:in `serialize': key $push must not start with '$' (BSON::InvalidKeyName)
What am I doing wrong?
It looks fine to me, and works for me. The following more exhaustive test works for me, please see if it works for you, and it should help to clarify your problem, which I suspect got lost while you were posting.
test_unit.rb:
require 'mongo'
require 'test/unit'
require 'json'
class MyTest < Test::Unit::TestCase
def setup
@coll = Mongo::MongoClient.new['some_app']['persons']
@coll.remove
end
test "BSON version" do
assert_equal("1.10.2", CBson::VERSION, "confirm loading of C extension and version")
end
test "$push to existing doc" do
json = %q{
{
"_id" : 5,
"tags" : ["Music", "Baseball", "Skiing"]
}
}
@coll.insert(JSON.parse(json))
@coll.update({_id: 5}, {"$push" => {tags: "PS4"}}, {upsert: true})
assert(@coll.find.to_a.first['tags'].include?('PS4'))
end
test "upsert and $push" do
@coll.update({_id: 5}, {"$push" => {tags: "PS4"}}, {upsert: true})
assert(@coll.find.to_a.first['tags'].include?('PS4'))
end
end
ruby -v test_unit.rb
ruby 2.1.1p76 (2014-02-24 revision 45161) [x86_64-darwin12.0]
osprey:free-59705-mongo-push gjm$ ruby test_unit.rb
Loaded suite test_unit
Started
...
Finished in 0.019441 seconds.
3 tests, 3 assertions, 0 failures, 0 errors, 0 pendings, 0 omissions, 0 notifications
100% passed
154.31 tests/s, 154.31 assertions/s