punkb
punkb

Reputation: 53

How to create model with an array field which contains another documents as an embedded documents in Mongodb (Mongoid)

I am using Rails 4 with Mongoid for an event based application. I am trying to create a model where I want to add an array field with embedded documents in that array. This embedded documents will contain user's geo coordinate and timestamp. After every 5 minutes I will be pushing user's latest coordinates to user's (location) array. can someone please help me, How can i create that.

My sample model and desired documents are as below.

class User
  include Mongoid::Document
  field :name, type: String

  field :locations, type: Array

end

Here I want to push

Here is sample document that I am looking for as a result:

{ _id : ObjectId(...),
  name : "User_name",
  locations : [ {
                 _id : ObjectID(...),
                 time : "...." ,
                 loc : [ 55.5, 42.3 ]
                } ,
                {
                 _id : ObjectID(...),
                 time : "...",
                 loc : [ -74 , 44.74 ]
                }
              ]
}

I was able to add the value in location array without embedded document through IRB, but as I will be using MongoDB's Geospatial queries later on, so I want to use 2D indexes and rest of the stuff Mongo Documentation mentioned. Hence I believe it needs to have array of documents which contain the latitude & longitude. which will also save my time to code.

Also can I make the time of the location as documents '_id' ? (It can help me to reduce the query overhead)

I would really appriciate if someone can help me with the structure of model i should write or guide me to the references.

P.S: Let me know if you suggest some extra references/help about storing geospatial data in mongoDB which can be helpful for me.

Upvotes: 1

Views: 2428

Answers (1)

AlkH
AlkH

Reputation: 321

Hope this will help somebody.

If you want to embed documents you can use embedded_many feature of mongoid, which handles such relations. It allows you to define index on embedded documents as well

http://mongoid.org/en/mongoid/docs/relations.html#embeds_many

Mongoid points out, that 2D indexes should be applied to arrays: http://mongoid.org/en/mongoid/docs/indexing.html

In your case models may look like this:

class User
  include Mongoid::Document

  field :name, type: String

  embeds_many :locations

  index({ "locations.loc" => "2d" })

  accepts_nested_attributes_for :locations # see http://mongoid.org/en/mongoid/docs/nested_attributes.html#common
end

class Location
  include Mongoid::Document

  field :time, type: DateTime # see http://mongoid.org/en/mongoid/docs/documents.html#fields
  field :loc, type: Array

  embedded_in :user
end

But beware of using update and nested attributes - it allows you only update attributes, but not delete or reject them. It's preferrable to use (association)_attributes= methods instead:

@user = User.new({ name: 'John Doe' })
@user.locations_attributes = {
  "0" => {
   _id : ObjectID(...),
   time : "...." ,
   loc : [ 55.5, 42.3 ]
  } ,
  "1" => {
   _id : ObjectID(...),
   time : "...",
   loc : [ -74 , 44.74 ]
  }
}
@user.save!

Upvotes: 1

Related Questions