// viewSave retrieve items for a view and saves those items to a new collection. func viewSave(context interface{}, mgoDB *db.DB, v *view.View, viewParams *ViewParams, ids []string, embeds embeddedRels) error { // Determine the buffer limit that will be used for saving this view. if viewParams.BufferLimit != 0 { bufferLimit = viewParams.BufferLimit } // Form the query. q := bson.M{"item_id": bson.M{"$in": ids}} results, err := mgoDB.BatchedQueryMGO(context, v.Collection, q) if err != nil { return err } // Set up a Bulk upsert. tx, err := mgoDB.BulkOperationMGO(context, viewParams.ResultsCollection) if err != nil { return err } // Group the embedded relationships by item and predicate/tag. embedByItem, err := groupEmbeds(embeds) if err != nil { return err } // Iterate over the view items. var queuedDocs int var result item.Item for results.Next(&result) { // Get the related IDs to embed. itemEmbeds, ok := embedByItem[result.ID] if ok { // Put the related IDs in the item. relMap := make(map[string]interface{}) for k, v := range itemEmbeds { relMap[k] = v } result.Related = relMap } // Queue the upsert of the result. tx.Upsert(bson.M{"item_id": result.ID}, result) queuedDocs++ // If the queued documents for upsert have reached the buffer limit, // run the bulk upsert and re-initialize the bulk operation. if queuedDocs >= bufferLimit { if _, err := tx.Run(); err != nil { return err } tx, err = mgoDB.BulkOperationMGO(context, viewParams.ResultsCollection) if err != nil { return err } queuedDocs = 0 } } if err := results.Close(); err != nil { return err } // Run the bulk operation for any remaining queued documents. if _, err := tx.Run(); err != nil { return err } return nil }