Search code examples
rubymongodbmongodb-ruby

ruby mongodb driver push to array


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?


Solution

  • 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