mongodb data design question
I'm trying my first application with mongodb on Rails using mongo_mapper and I'm weighing my options on an STI model like below.
It works fine, and I will of course add to this in more ways than I can currently count, I just curious if I wouldn't be better off with Embedded Documents or some such.
I'd like my models to share as much as possible, IE since they all inherit certain attributes, a shared 开发者_如何转开发form partial on property/_form.html.erb... in addition to their own unique form elements etc. I know the views will differ but I'm not sure on the controllers yet, as I could use property controller I assume for most things? And I'm sure it will get more complex as I go along.
Any pointers resources and/or wisdom (pain saving tips) would be greatly appreciated
property.rb
class Property
include MongoMapper::Document
key :name, String, :required => true
key :_type, String, :required => true
key :location_id, Integer, :required => true
key :description, String
key :phone, String
key :address, String
key :url, String
key :lat, Numeric
key :lng, Numeric
key :user_id, Integer, :required => true
timestamps!
end
restaurant
class Restaurant < Property
key :cuisine_types, Array, :required => true
end
bar
class Bar < Property
key :beers_on_tap, Array
end
Don't be afraid of more models, the idea of OO is to be able to cut up your concerns into tiny pieces and then treat each of them in the way they need to be treated.
For example, your Property model seems to be doing a whole lot. Why not split out the geo stuff you've got going on into an EmbeddedDocument (lat, lng, address, etc)? That way your code will remain simpler and more readable.
I use this sort of STI myself and I find it makes my code much simpler and more useable. One of the beauties of using a DB like Mongo is that you can do very complex STI like this and still have a manageable collection of data.
Regarding your cuisine_types and beers_on_tap etc, I think those are fine concepts. It might be useful to have Cuisine and Beer models too, so your database remains more normalized (a concept that is easy to lose in Mongo). e.g.:
class Bar < Property
key :beer_ids, Array
many :beers, :in => :beer_ids
end
class Beer
include MongoMapper:Document
key :name, String
end
Do you expect to return both Restaurants and Bars in the same query?
If not, you might want to reconsider having them derive from a base type.
By default, Mongo_Mapper is going to put both Restaurants and Bars in a single collection. This could hamper performance and make things harder to scale in the future.
Looking through some of the Mongo_Mapper code, it looks like you might be able to set this on the fly with set_collection_name.
精彩评论