41

I googled and all others, but I didn't find the answer. The question is:

Hi, how can I do batch insert with Mongoid to MongoDB?

millisami
  • 9,931
  • 15
  • 70
  • 112

4 Answers4

55

You can insert a batch array of hashes using the ruby mongo driver's insert method. From any Mongoid class, you can call collection to access it.

batch = [{:name => "mongodb"}, {:name => "mongoid"}]  
Article.collection.insert(batch)
tommy chheng
  • 9,108
  • 9
  • 55
  • 72
  • 5
    A very important point to remember is that by doing this you are bypassing mongoid.yml options. So if you use it, make sure to inform them if you need, e.g.: Article.with(safe: true).collection.insert(batch) – bakkay Jul 10 '14 at 18:51
  • 1
    I'm receiving NoMethodError: undefined method `insert' – tomascharad Nov 11 '15 at 14:04
  • Me too. Asked a question about it http://stackoverflow.com/questions/33894132/mongocollection-undefined-method-insert – Mika Nov 24 '15 at 13:04
  • For `undefined method 'insert'` try bellow answer using `create` – Haris Krajina Feb 11 '16 at 14:25
  • 4
    @HarisKrajina - In the updated version of mongoid you will need to use the 'insert_many' method. Hope this helps, – max kaplan Jul 18 '16 at 23:02
  • @maxkaplan - Mongoid does not seem to have this anymore: https://docs.mongodb.com/ruby-driver/master/tutorials/6.1.0/mongoid-persistence/ – B Seven Mar 14 '17 at 21:03
  • As of Mongoid 7 `insert` has been replace with `insert_many`: `Article.collection.insert_many(batch)` – B Seven Jul 31 '22 at 04:45
  • @HarisKrajina - `create` does not do batch insert. – B Seven Jul 31 '22 at 04:46
26

If you want to batch insert Mongoid documents (models) instead of hashes, call your model's as_document method before placing it into array:

@page_views << page_view.as_document

...

PageView.collection.insert(@page_views)
Damir Bulic
  • 2,209
  • 1
  • 15
  • 7
  • 1
    I get this error undefined method `as_document' for # any solution ? – Abhay Kumar Jul 03 '12 at 10:24
  • @AbhayKumar `as_document` doesn't work against an array, only single objects. If you already have an array of objects, you can call it like so: `PageView.collection.insert(@page_views.map(&:as_document))` which will map all of the objects to documents prior to insertion. – Jay Apr 19 '13 at 06:59
  • 2
    @Jay Does `mongoid` or `mongodb` solve out the fact that an object already exists and perform an update? Or is it necessary to filter those out? – tolgap Jan 09 '14 at 14:59
  • 1
    @tolgap As far as I'm aware Mongoid ignores all validations in this instance (including uniqueness checks), so I doubt it. I can't test as I'm not using either in my current project, but I would say insertion of duplicates would be the most likely outcome by far :) Try it out and let me know how it goes! – Jay Jan 10 '14 at 00:52
  • 1
    RE: last two commenters, collection.insert will create duplicates and performs no update or find_or_create_by like operations. But it is a lot faster! I ran a benchmark test and found that I could insert 1000 records with collection.insert in 0.07 seconds, whereas inserting 1000 records with find_or_create_by took 3.35 seconds. – quetzaluz Sep 23 '14 at 21:57
11

You can use this:

books = [{:name => "Harry Potter"}, {:name => "Night"}]  
Book.collection.insert_many(books)

And I find that "insert" does not work for me(Monogoid 5.1.3):

NoMethodError: undefined method `insert' for # <Mongo::Collection:0x007fbdbc9b1cd0>
Did you mean?  insert_one
               insert_many
               inspect

This is the source code from "lib/mongo/collection.rb":

# Insert the provided documents into the collection.
#
# @example Insert documents into the collection.
#   collection.insert_many([{ name: 'test' }])
#
# @param [ Array<Hash> ] documents The documents to insert.
# @param [ Hash ] options The insert options.
#
# @return [ Result ] The database response wrapper.
#
# @since 2.0.0
def insert_many(documents, options = {})
  inserts = documents.map{ |doc| { :insert_one => doc }}
  bulk_write(inserts, options)
end
liukgg
  • 226
  • 3
  • 6
5

Mongoid's Model.create method can accept an array to create documents.

From the Mongoid docs:

Person.create([
  { first_name: "Heinrich", last_name: "Heine" },
  { first_name: "Willy", last_name: "Brandt" }
])

https://docs.mongodb.org/ecosystem/tutorial/mongoid-persistence/

Litty
  • 1,856
  • 1
  • 16
  • 35
dcrane
  • 51
  • 1
  • 2