开发者

Ruby Mongo::ObjectID comparison

SO,

I have two Mongo::ObjectID objects that are equal according to both == and eql? (they both return true). However, if one is a key in a Hash and the other is in a document stored in an array, this fails:

myhash[array_of_docs[0]['_id']] # => nil
myhash.fetch(array_of_docs[0]['_id']) # => KeyError: key not found

My db has 2 collections, "bookmarks", with mainly a title and url, and "tags", with a 'bkm_id' key pointing to a bookmark doc's _id and a 'name' key. With the following query, I map each bookmark's _id to the corresponding comma-separated list of tags:

bkms_tags_array = tags_collection.group(['bkm_id'], nil, { tags: Array.new }, "function(tag, agg){ agg.tags.push(tag.name) }", true)
bkms_tags = {}
bkms_tags_array.each do |bt|
    bkms_tags.merge! Hash[bt.values[0], bt.values[1].join(", ")]
end
bkms_tags # => {4d60b29603e5665f82000001=>"socialnw, blablabla", 4d60b44703e5665fff000001=>"mail, app, google", 4d61812f03e5661ad8000001=>"socialnw, comms, web"}

Given that bks is the result of 'bookmarks_collection.find.to_a', this is my problem:

bkms_tags[bks[0]['_id']] # => nil
bkms_tags.include? bks[0]['_id'] # => false ; however:
bkms_tags.keys.include? bks[0]['_id'] # => true

How come 'hash.include?' be false and 'hash.keys.include?' be true? Is there a difference between ObjectIDs returned by different queries?

Like I said, both == and eql? return true:

bkms_tags.each { |k,v| puts k == bks[0]['_id'] } # => true false false
bkms_tags.keys.each { |k| puts k == bks[0]['_id'] } # => true false false
bkms_tags.each { |k,v| puts k.eql? bks[0]['_id'] } # => true false false
bkms_tags.keys.each { |k| puts k.eql? bks[0]['_id'] } # => true false false

So, by any comparison possible, 'bks[0]['_id']' is a key of bkms_tags, but when I try to retrieve it's value, Ruby gets confused somehow.

Any ideas? Thanks!

Extra info:

Some sample documents:

Bookmarks

{ "_id" : ObjectId("4d60b29603e5665f82000001"), "url" : "http://www.facebook.com/", "title" : "Facebook", "host" : "facebook.com", "saved_at" : "Sun Feb 20 2011 01:20:06 GMT-0500 (PET)" }
{ "_id" : ObjectId("4d60b44703e5665fff000001"), "url" : "http://mail.google.com/", "title" : "gmail", "host" : "mail.google.com", "saved_at" : "Sun Feb 20 2011 01:27:19 GMT-0500 (PET)" }
{ "_id" : ObjectId("4d61812f03e5661ad8000001"), "url" : "http://twitter.com/", "title" : "twitter", "host" : "twitter.com", "saved_at" : "Sun Feb 20 2011 16:01:35 GMT-0500 (PET)" }

Tags

{ "_id" : ObjectId("4d60b44703e5665fff000002"), "bkm_id" : ObjectId("4d60b44703e5665fff000001"), "name" : "mail开发者_高级运维" }
{ "_id" : ObjectId("4d60b44703e5665fff000003"), "bkm_id" : ObjectId("4d60b44703e5665fff000001"), "name" : "app" }
{ "_id" : ObjectId("4d60b29603e5665f82000003"), "bkm_id" : ObjectId("4d60b29603e5665f82000001"), "name" : "socialnw" }
{ "_id" : ObjectId("4d60b29603e5665f82000004"), "bkm_id" : ObjectId("4d60b29603e5665f82000001"), "name" : "blablabla" }
{ "_id" : ObjectId("4d61812f03e5661ad8000003"), "bkm_id" : ObjectId("4d61812f03e5661ad8000001"), "name" : "comms" }
{ "_id" : ObjectId("4d61812f03e5661ad8000004"), "bkm_id" : ObjectId("4d61812f03e5661ad8000001"), "name" : "web" }

EDIT

Testing some more, I came up with more irregularities:

bkms_ids # => [4d60b29603e5665f82000001, 4d61812f03e5661ad8000001, 4d61ba9103e5667dbe000001, 4d61ba9103e5667dbe000001]
bkms_ids[2] == bkms_ids[3] # => true
bkms_ids[2].eql? bkms_ids[3] # => true
bkms_ids.uniq # => nothing changes: [4d60b29603e5665f82000001, 4d61812f03e5661ad8000001, 4d61ba9103e5667dbe000001, 4d61ba9103e5667dbe000001]

EDIT 2

As requested, my bson version:

irb> BSON::VERSION # NameError: uninitialized constant BSON::VERSION
$ gem list bson

*** LOCAL GEMS ***

bson (1.2.2)
bson_ext (1.2.2)

and inspect and class of my array of docs:

array_of_docs = bookmarks_collection.find.to_a
array_of_docs[0].inspect # => "{\"_id\"=>4d60b29603e5665f82000001, \"url\"=>\"http://www.facebook.com/\", \"title\"=>\"Facebook\", \"host\"=>\"facebook.com\", \"saved_at\"=>2011-02-20 06:20:06 UTC}"
array_of_docs[0].class # => OrderedHash
array_of_docs[0]['_id'].class # => Mongo::ObjectID


Change uniq to uniq! :

bkms_ids

bkms_ids[2] == bkms_ids[3]

bkms_ids[2].eql? bkms_ids[3]

bkms_ids.uniq!

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜