Cjoerg
Cjoerg

Reputation: 1325

MongoDB creates parent objects when I try to create child objects

This model:

class SimCustomer < Customer
  index({ user_id: 1 },       { background: true })
  belongs_to :user,           :inverse_of => :sim_customers
end

inherits from this model:

class Customer
  include Mongoid::Document
  include Mongoid::Timestamps
  field :mail_address,        type: String
end

I create the indexes from my terminal:

bundle exec rake db:mongoid:create_indexes

But this creates indexes on the Customer instead of the SimCustomer:

I, [2014-11-13T16:21:17.210343 #11407]  INFO -- : MONGOID: Created indexes on Customer:
I, [2014-11-13T16:21:17.210381 #11407]  INFO -- : MONGOID: Index: {:user_id=>1}, Options: {:background=>true}

And when I try to batch insert SimCustomer objects it creates Customer objects instead:

SimCustomer.collection.insert(Array.new << {mail_address: "[email protected]", user_id: "54652f5b43687229b4060000"})
# => #<Customer _id: 54654b7b6220ff4f28364ee9, created_at: nil, updated_at: nil, mail_address: "[email protected]", _type: "Customer">

How can I fix this?

Upvotes: 1

Views: 295

Answers (1)

mu is too short
mu is too short

Reputation: 434825

This sets up Single Collection Inheritance:

class SimCustomer < Customer

That means that both Customer and SimCustomer will be stored in the customers collection inside MongoDB and they'll be differentiated using the _type field.

Specifying an index in SimCustomer:

class SimCustomer < Customer
  index({ user_id: 1 },       { background: true })

will create the index on the customers collection because that's where SimCustomers are stored.

The same collection chicanery is causing your problem with your bulk insert. If you look at SimCustomer.collection.name you'll find that it says 'customers' so of course SimCustomer.collection.insert will create new Customers. If you want to create SimCustomers by hand then specify the _type:

SimCustomer.collection.insert(
  _type: 'SimCustomer',
  mail_address: "[email protected]",
  user_id: "54652f5b43687229b4060000"
)

Note that I dropped that strange looking Array.new << stuff, I don't know where you learned that from but it is unnecessary when inserting on object and odd looking if you were inserting several, if you want to insert several then just use an array literal:

SimCustomer.collection.insert([
  { ... },
  { ... },
  ...
])

Your next problem is going to be that string in user_id. That really should be a Moped::BSON::ObjectId or you'll end up with a string inside the database and that will make a mess of your queries. Mongoid may know what type a property should be but neither Moped nor MongoDB will. You'll want to use Moped::BSON::ObjectId('54652f5b43687229b4060000') instead.

Upvotes: 2

Related Questions