seba-365 - implemented dep

Change-Id: Ia6226d50e7615935a0c8876809a687427ff88c22
diff --git a/vendor/github.com/mongodb/mongo-go-driver/mongo/batch_cursor.go b/vendor/github.com/mongodb/mongo-go-driver/mongo/batch_cursor.go
new file mode 100644
index 0000000..a7ce0b5
--- /dev/null
+++ b/vendor/github.com/mongodb/mongo-go-driver/mongo/batch_cursor.go
@@ -0,0 +1,30 @@
+package mongo
+
+import (
+	"context"
+)
+
+// batchCursor is the interface implemented by types that can provide batches of document results.
+// The Cursor type is built on top of this type.
+type batchCursor interface {
+	// ID returns the ID of the cursor.
+	ID() int64
+
+	// Next returns true if there is a batch available.
+	Next(context.Context) bool
+
+	// Batch appends the current batch of documents to dst. RequiredBytes can be used to determine
+	// the length of the current batch of documents.
+	//
+	// If there is no batch available, this method should do nothing.
+	Batch(dst []byte) []byte
+
+	// RequiredBytes returns the number of bytes required fo rthe current batch.
+	RequiredBytes() int
+
+	// Err returns the last error encountered.
+	Err() error
+
+	// Close closes the cursor.
+	Close(context.Context) error
+}
diff --git a/vendor/github.com/mongodb/mongo-go-driver/mongo/bulk_write.go b/vendor/github.com/mongodb/mongo-go-driver/mongo/bulk_write.go
new file mode 100644
index 0000000..f086189
--- /dev/null
+++ b/vendor/github.com/mongodb/mongo-go-driver/mongo/bulk_write.go
@@ -0,0 +1,341 @@
+// Copyright (C) MongoDB, Inc. 2017-present.
+//
+// Licensed under the Apache License, Version 2.0 (the "License"); you may
+// not use this file except in compliance with the License. You may obtain
+// a copy of the License at http://www.apache.org/licenses/LICENSE-2.0
+
+package mongo
+
+import (
+	"github.com/mongodb/mongo-go-driver/mongo/options"
+	"github.com/mongodb/mongo-go-driver/x/mongo/driver"
+)
+
+// WriteModel is the interface satisfied by all models for bulk writes.
+type WriteModel interface {
+	convertModel() driver.WriteModel
+}
+
+// InsertOneModel is the write model for insert operations.
+type InsertOneModel struct {
+	Document interface{}
+}
+
+// NewInsertOneModel creates a new InsertOneModel.
+func NewInsertOneModel() *InsertOneModel {
+	return &InsertOneModel{}
+}
+
+// SetDocument sets the BSON document for the InsertOneModel.
+func (iom *InsertOneModel) SetDocument(doc interface{}) *InsertOneModel {
+	iom.Document = doc
+	return iom
+}
+
+func (iom *InsertOneModel) convertModel() driver.WriteModel {
+	return driver.InsertOneModel{
+		Document: iom.Document,
+	}
+}
+
+// DeleteOneModel is the write model for delete operations.
+type DeleteOneModel struct {
+	Filter    interface{}
+	Collation *options.Collation
+}
+
+// NewDeleteOneModel creates a new DeleteOneModel.
+func NewDeleteOneModel() *DeleteOneModel {
+	return &DeleteOneModel{}
+}
+
+// SetFilter sets the filter for the DeleteOneModel.
+func (dom *DeleteOneModel) SetFilter(filter interface{}) *DeleteOneModel {
+	dom.Filter = filter
+	return dom
+}
+
+// SetCollation sets the collation for the DeleteOneModel.
+func (dom *DeleteOneModel) SetCollation(collation *options.Collation) *DeleteOneModel {
+	dom.Collation = collation
+	return dom
+}
+
+func (dom *DeleteOneModel) convertModel() driver.WriteModel {
+	return driver.DeleteOneModel{
+		Collation: dom.Collation,
+		Filter:    dom.Filter,
+	}
+}
+
+// DeleteManyModel is the write model for deleteMany operations.
+type DeleteManyModel struct {
+	Filter    interface{}
+	Collation *options.Collation
+}
+
+// NewDeleteManyModel creates a new DeleteManyModel.
+func NewDeleteManyModel() *DeleteManyModel {
+	return &DeleteManyModel{}
+}
+
+// SetFilter sets the filter for the DeleteManyModel.
+func (dmm *DeleteManyModel) SetFilter(filter interface{}) *DeleteManyModel {
+	dmm.Filter = filter
+	return dmm
+}
+
+// SetCollation sets the collation for the DeleteManyModel.
+func (dmm *DeleteManyModel) SetCollation(collation *options.Collation) *DeleteManyModel {
+	dmm.Collation = collation
+	return dmm
+}
+
+func (dmm *DeleteManyModel) convertModel() driver.WriteModel {
+	return driver.DeleteManyModel{
+		Collation: dmm.Collation,
+		Filter:    dmm.Filter,
+	}
+}
+
+// ReplaceOneModel is the write model for replace operations.
+type ReplaceOneModel struct {
+	Collation   *options.Collation
+	Upsert      *bool
+	Filter      interface{}
+	Replacement interface{}
+}
+
+// NewReplaceOneModel creates a new ReplaceOneModel.
+func NewReplaceOneModel() *ReplaceOneModel {
+	return &ReplaceOneModel{}
+}
+
+// SetFilter sets the filter for the ReplaceOneModel.
+func (rom *ReplaceOneModel) SetFilter(filter interface{}) *ReplaceOneModel {
+	rom.Filter = filter
+	return rom
+}
+
+// SetReplacement sets the replacement document for the ReplaceOneModel.
+func (rom *ReplaceOneModel) SetReplacement(rep interface{}) *ReplaceOneModel {
+	rom.Replacement = rep
+	return rom
+}
+
+// SetCollation sets the collation for the ReplaceOneModel.
+func (rom *ReplaceOneModel) SetCollation(collation *options.Collation) *ReplaceOneModel {
+	rom.Collation = collation
+	return rom
+}
+
+// SetUpsert specifies if a new document should be created if no document matches the query.
+func (rom *ReplaceOneModel) SetUpsert(upsert bool) *ReplaceOneModel {
+	rom.Upsert = &upsert
+	return rom
+}
+
+func (rom *ReplaceOneModel) convertModel() driver.WriteModel {
+	um := driver.UpdateModel{
+		Collation: rom.Collation,
+	}
+	if rom.Upsert != nil {
+		um.Upsert = *rom.Upsert
+		um.UpsertSet = true
+	}
+
+	return driver.ReplaceOneModel{
+		UpdateModel: um,
+		Filter:      rom.Filter,
+		Replacement: rom.Replacement,
+	}
+}
+
+// UpdateOneModel is the write model for update operations.
+type UpdateOneModel struct {
+	Collation    *options.Collation
+	Upsert       *bool
+	Filter       interface{}
+	Update       interface{}
+	ArrayFilters *options.ArrayFilters
+}
+
+// NewUpdateOneModel creates a new UpdateOneModel.
+func NewUpdateOneModel() *UpdateOneModel {
+	return &UpdateOneModel{}
+}
+
+// SetFilter sets the filter for the UpdateOneModel.
+func (uom *UpdateOneModel) SetFilter(filter interface{}) *UpdateOneModel {
+	uom.Filter = filter
+	return uom
+}
+
+// SetUpdate sets the update document for the UpdateOneModel.
+func (uom *UpdateOneModel) SetUpdate(update interface{}) *UpdateOneModel {
+	uom.Update = update
+	return uom
+}
+
+// SetArrayFilters specifies a set of filters specifying to which array elements an update should apply.
+func (uom *UpdateOneModel) SetArrayFilters(filters options.ArrayFilters) *UpdateOneModel {
+	uom.ArrayFilters = &filters
+	return uom
+}
+
+// SetCollation sets the collation for the UpdateOneModel.
+func (uom *UpdateOneModel) SetCollation(collation *options.Collation) *UpdateOneModel {
+	uom.Collation = collation
+	return uom
+}
+
+// SetUpsert specifies if a new document should be created if no document matches the query.
+func (uom *UpdateOneModel) SetUpsert(upsert bool) *UpdateOneModel {
+	uom.Upsert = &upsert
+	return uom
+}
+
+func (uom *UpdateOneModel) convertModel() driver.WriteModel {
+	um := driver.UpdateModel{
+		Collation: uom.Collation,
+	}
+	if uom.Upsert != nil {
+		um.Upsert = *uom.Upsert
+		um.UpsertSet = true
+	}
+
+	converted := driver.UpdateOneModel{
+		UpdateModel: um,
+		Filter:      uom.Filter,
+		Update:      uom.Update,
+	}
+	if uom.ArrayFilters != nil {
+		converted.ArrayFilters = *uom.ArrayFilters
+		converted.ArrayFiltersSet = true
+	}
+
+	return converted
+}
+
+// UpdateManyModel is the write model for updateMany operations.
+type UpdateManyModel struct {
+	Collation    *options.Collation
+	Upsert       *bool
+	Filter       interface{}
+	Update       interface{}
+	ArrayFilters *options.ArrayFilters
+}
+
+// NewUpdateManyModel creates a new UpdateManyModel.
+func NewUpdateManyModel() *UpdateManyModel {
+	return &UpdateManyModel{}
+}
+
+// SetFilter sets the filter for the UpdateManyModel.
+func (umm *UpdateManyModel) SetFilter(filter interface{}) *UpdateManyModel {
+	umm.Filter = filter
+	return umm
+}
+
+// SetUpdate sets the update document for the UpdateManyModel.
+func (umm *UpdateManyModel) SetUpdate(update interface{}) *UpdateManyModel {
+	umm.Update = update
+	return umm
+}
+
+// SetArrayFilters specifies a set of filters specifying to which array elements an update should apply.
+func (umm *UpdateManyModel) SetArrayFilters(filters options.ArrayFilters) *UpdateManyModel {
+	umm.ArrayFilters = &filters
+	return umm
+}
+
+// SetCollation sets the collation for the UpdateManyModel.
+func (umm *UpdateManyModel) SetCollation(collation *options.Collation) *UpdateManyModel {
+	umm.Collation = collation
+	return umm
+}
+
+// SetUpsert specifies if a new document should be created if no document matches the query.
+func (umm *UpdateManyModel) SetUpsert(upsert bool) *UpdateManyModel {
+	umm.Upsert = &upsert
+	return umm
+}
+
+func (umm *UpdateManyModel) convertModel() driver.WriteModel {
+	um := driver.UpdateModel{
+		Collation: umm.Collation,
+	}
+	if umm.Upsert != nil {
+		um.Upsert = *umm.Upsert
+		um.UpsertSet = true
+	}
+
+	converted := driver.UpdateManyModel{
+		UpdateModel: um,
+		Filter:      umm.Filter,
+		Update:      umm.Update,
+	}
+	if umm.ArrayFilters != nil {
+		converted.ArrayFilters = *umm.ArrayFilters
+		converted.ArrayFiltersSet = true
+	}
+
+	return converted
+}
+
+func dispatchToMongoModel(model driver.WriteModel) WriteModel {
+	switch conv := model.(type) {
+	case driver.InsertOneModel:
+		return &InsertOneModel{
+			Document: conv.Document,
+		}
+	case driver.DeleteOneModel:
+		return &DeleteOneModel{
+			Filter:    conv.Filter,
+			Collation: conv.Collation,
+		}
+	case driver.DeleteManyModel:
+		return &DeleteManyModel{
+			Filter:    conv.Filter,
+			Collation: conv.Collation,
+		}
+	case driver.ReplaceOneModel:
+		rom := &ReplaceOneModel{
+			Filter:      conv.Filter,
+			Replacement: conv.Replacement,
+			Collation:   conv.Collation,
+		}
+		if conv.UpsertSet {
+			rom.Upsert = &conv.Upsert
+		}
+		return rom
+	case driver.UpdateOneModel:
+		uom := &UpdateOneModel{
+			Filter:    conv.Filter,
+			Update:    conv.Update,
+			Collation: conv.Collation,
+		}
+		if conv.UpsertSet {
+			uom.Upsert = &conv.Upsert
+		}
+		if conv.ArrayFiltersSet {
+			uom.ArrayFilters = &conv.ArrayFilters
+		}
+		return uom
+	case driver.UpdateManyModel:
+		umm := &UpdateManyModel{
+			Filter:    conv.Filter,
+			Update:    conv.Update,
+			Collation: conv.Collation,
+		}
+		if conv.UpsertSet {
+			umm.Upsert = &conv.Upsert
+		}
+		if conv.ArrayFiltersSet {
+			umm.ArrayFilters = &conv.ArrayFilters
+		}
+		return umm
+	}
+
+	return nil
+}
diff --git a/vendor/github.com/mongodb/mongo-go-driver/mongo/change_stream.go b/vendor/github.com/mongodb/mongo-go-driver/mongo/change_stream.go
new file mode 100644
index 0000000..5330117
--- /dev/null
+++ b/vendor/github.com/mongodb/mongo-go-driver/mongo/change_stream.go
@@ -0,0 +1,508 @@
+// Copyright (C) MongoDB, Inc. 2017-present.
+//
+// Licensed under the Apache License, Version 2.0 (the "License"); you may
+// not use this file except in compliance with the License. You may obtain
+// a copy of the License at http://www.apache.org/licenses/LICENSE-2.0
+
+package mongo
+
+import (
+	"context"
+	"errors"
+	"time"
+
+	"github.com/mongodb/mongo-go-driver/bson"
+	"github.com/mongodb/mongo-go-driver/bson/bsoncodec"
+	"github.com/mongodb/mongo-go-driver/mongo/options"
+	"github.com/mongodb/mongo-go-driver/mongo/readconcern"
+	"github.com/mongodb/mongo-go-driver/mongo/readpref"
+	"github.com/mongodb/mongo-go-driver/x/bsonx"
+	"github.com/mongodb/mongo-go-driver/x/bsonx/bsoncore"
+	"github.com/mongodb/mongo-go-driver/x/mongo/driver"
+	"github.com/mongodb/mongo-go-driver/x/mongo/driver/session"
+	"github.com/mongodb/mongo-go-driver/x/network/command"
+	"github.com/mongodb/mongo-go-driver/x/network/description"
+)
+
+const errorInterrupted int32 = 11601
+const errorCappedPositionLost int32 = 136
+const errorCursorKilled int32 = 237
+
+// ErrMissingResumeToken indicates that a change stream notification from the server did not
+// contain a resume token.
+var ErrMissingResumeToken = errors.New("cannot provide resume functionality when the resume token is missing")
+
+// ErrNilCursor indicates that the cursor for the change stream is nil.
+var ErrNilCursor = errors.New("cursor is nil")
+
+// ChangeStream instances iterate a stream of change documents. Each document can be decoded via the
+// Decode method. Resume tokens should be retrieved via the ResumeToken method and can be stored to
+// resume the change stream at a specific point in time.
+//
+// A typical usage of the ChangeStream type would be:
+type ChangeStream struct {
+	// Current is the BSON bytes of the current change document. This property is only valid until
+	// the next call to Next or Close. If continued access is required to the bson.Raw, you must
+	// make a copy of it.
+	Current bson.Raw
+
+	cmd        bsonx.Doc // aggregate command to run to create stream and rebuild cursor
+	pipeline   bsonx.Arr
+	options    *options.ChangeStreamOptions
+	coll       *Collection
+	db         *Database
+	ns         command.Namespace
+	cursor     *Cursor
+	cursorOpts bsonx.Doc
+
+	resumeToken bsonx.Doc
+	err         error
+	streamType  StreamType
+	client      *Client
+	sess        Session
+	readPref    *readpref.ReadPref
+	readConcern *readconcern.ReadConcern
+	registry    *bsoncodec.Registry
+}
+
+func (cs *ChangeStream) replaceOptions(desc description.SelectedServer) {
+	// if cs has not received any changes and resumeAfter not specified and max wire version >= 7, run known agg cmd
+	// with startAtOperationTime set to startAtOperationTime provided by user or saved from initial agg
+	// must not send resumeAfter key
+
+	// else: run known agg cmd with resumeAfter set to last known resumeToken
+	// must not set startAtOperationTime (remove if originally in cmd)
+
+	if cs.options.ResumeAfter == nil && desc.WireVersion.Max >= 7 && cs.resumeToken == nil {
+		cs.options.SetStartAtOperationTime(cs.sess.OperationTime())
+	} else {
+		if cs.resumeToken == nil {
+			return // restart stream without the resume token
+		}
+
+		cs.options.SetResumeAfter(cs.resumeToken)
+		// remove startAtOperationTime
+		cs.options.SetStartAtOperationTime(nil)
+	}
+}
+
+// Create options docs for the pipeline and cursor
+func createCmdDocs(csType StreamType, opts *options.ChangeStreamOptions, registry *bsoncodec.Registry) (bsonx.Doc,
+	bsonx.Doc, bsonx.Doc, error) {
+
+	pipelineDoc := bsonx.Doc{}
+	cursorDoc := bsonx.Doc{}
+	optsDoc := bsonx.Doc{}
+
+	if csType == ClientStream {
+		pipelineDoc = pipelineDoc.Append("allChangesForCluster", bsonx.Boolean(true))
+	}
+
+	if opts.BatchSize != nil {
+		cursorDoc = cursorDoc.Append("batchSize", bsonx.Int32(*opts.BatchSize))
+	}
+	if opts.Collation != nil {
+		optsDoc = optsDoc.Append("collation", bsonx.Document(opts.Collation.ToDocument()))
+	}
+	if opts.FullDocument != nil {
+		pipelineDoc = pipelineDoc.Append("fullDocument", bsonx.String(string(*opts.FullDocument)))
+	}
+	if opts.MaxAwaitTime != nil {
+		ms := int64(time.Duration(*opts.MaxAwaitTime) / time.Millisecond)
+		pipelineDoc = pipelineDoc.Append("maxAwaitTimeMS", bsonx.Int64(ms))
+	}
+	if opts.ResumeAfter != nil {
+		rt, err := transformDocument(registry, opts.ResumeAfter)
+		if err != nil {
+			return nil, nil, nil, err
+		}
+
+		pipelineDoc = pipelineDoc.Append("resumeAfter", bsonx.Document(rt))
+	}
+	if opts.StartAtOperationTime != nil {
+		pipelineDoc = pipelineDoc.Append("startAtOperationTime",
+			bsonx.Timestamp(opts.StartAtOperationTime.T, opts.StartAtOperationTime.I))
+	}
+
+	return pipelineDoc, cursorDoc, optsDoc, nil
+}
+
+func getSession(ctx context.Context, client *Client) (Session, error) {
+	sess := sessionFromContext(ctx)
+	if err := client.ValidSession(sess); err != nil {
+		return nil, err
+	}
+
+	var mongoSess Session
+	if sess != nil {
+		mongoSess = &sessionImpl{
+			Client: sess,
+		}
+	} else {
+		// create implicit session because it will be needed
+		newSess, err := session.NewClientSession(client.topology.SessionPool, client.id, session.Implicit)
+		if err != nil {
+			return nil, err
+		}
+
+		mongoSess = &sessionImpl{
+			Client: newSess,
+		}
+	}
+
+	return mongoSess, nil
+}
+
+func parseOptions(csType StreamType, opts *options.ChangeStreamOptions, registry *bsoncodec.Registry) (bsonx.Doc,
+	bsonx.Doc, bsonx.Doc, error) {
+
+	if opts.FullDocument == nil {
+		opts = opts.SetFullDocument(options.Default)
+	}
+
+	pipelineDoc, cursorDoc, optsDoc, err := createCmdDocs(csType, opts, registry)
+	if err != nil {
+		return nil, nil, nil, err
+	}
+
+	return pipelineDoc, cursorDoc, optsDoc, nil
+}
+
+func (cs *ChangeStream) runCommand(ctx context.Context, replaceOptions bool) error {
+	ss, err := cs.client.topology.SelectServer(ctx, cs.db.writeSelector)
+	if err != nil {
+		return err
+	}
+
+	desc := ss.Description()
+	conn, err := ss.Connection(ctx)
+	if err != nil {
+		return err
+	}
+	defer conn.Close()
+
+	if replaceOptions {
+		cs.replaceOptions(desc)
+		optionsDoc, _, _, err := createCmdDocs(cs.streamType, cs.options, cs.registry)
+		if err != nil {
+			return err
+		}
+
+		changeStreamDoc := bsonx.Doc{
+			{"$changeStream", bsonx.Document(optionsDoc)},
+		}
+		cs.pipeline[0] = bsonx.Document(changeStreamDoc)
+		cs.cmd.Set("pipeline", bsonx.Array(cs.pipeline))
+	}
+
+	readCmd := command.Read{
+		DB:          cs.db.name,
+		Command:     cs.cmd,
+		Session:     cs.sess.(*sessionImpl).Client,
+		Clock:       cs.client.clock,
+		ReadPref:    cs.readPref,
+		ReadConcern: cs.readConcern,
+	}
+
+	rdr, err := readCmd.RoundTrip(ctx, desc, conn)
+	if err != nil {
+		cs.sess.EndSession(ctx)
+		return err
+	}
+
+	batchCursor, err := driver.NewBatchCursor(bsoncore.Document(rdr), readCmd.Session, readCmd.Clock, ss.Server)
+	if err != nil {
+		cs.sess.EndSession(ctx)
+		return err
+	}
+	cursor, err := newCursor(batchCursor, cs.registry)
+	if err != nil {
+		cs.sess.EndSession(ctx)
+		return err
+	}
+	cs.cursor = cursor
+
+	cursorValue, err := rdr.LookupErr("cursor")
+	if err != nil {
+		return err
+	}
+	cursorDoc := cursorValue.Document()
+	cs.ns = command.ParseNamespace(cursorDoc.Lookup("ns").StringValue())
+
+	return nil
+}
+
+func newChangeStream(ctx context.Context, coll *Collection, pipeline interface{},
+	opts ...*options.ChangeStreamOptions) (*ChangeStream, error) {
+
+	pipelineArr, err := transformAggregatePipeline(coll.registry, pipeline)
+	if err != nil {
+		return nil, err
+	}
+
+	csOpts := options.MergeChangeStreamOptions(opts...)
+	pipelineDoc, cursorDoc, optsDoc, err := parseOptions(CollectionStream, csOpts, coll.registry)
+	if err != nil {
+		return nil, err
+	}
+	sess, err := getSession(ctx, coll.client)
+	if err != nil {
+		return nil, err
+	}
+
+	csDoc := bsonx.Document(bsonx.Doc{
+		{"$changeStream", bsonx.Document(pipelineDoc)},
+	})
+	pipelineArr = append(bsonx.Arr{csDoc}, pipelineArr...)
+
+	cmd := bsonx.Doc{
+		{"aggregate", bsonx.String(coll.name)},
+		{"pipeline", bsonx.Array(pipelineArr)},
+		{"cursor", bsonx.Document(cursorDoc)},
+	}
+	cmd = append(cmd, optsDoc...)
+
+	cs := &ChangeStream{
+		client:      coll.client,
+		sess:        sess,
+		cmd:         cmd,
+		pipeline:    pipelineArr,
+		coll:        coll,
+		db:          coll.db,
+		streamType:  CollectionStream,
+		readPref:    coll.readPreference,
+		readConcern: coll.readConcern,
+		options:     csOpts,
+		registry:    coll.registry,
+		cursorOpts:  cursorDoc,
+	}
+
+	err = cs.runCommand(ctx, false)
+	if err != nil {
+		return nil, err
+	}
+
+	return cs, nil
+}
+
+func newDbChangeStream(ctx context.Context, db *Database, pipeline interface{},
+	opts ...*options.ChangeStreamOptions) (*ChangeStream, error) {
+
+	pipelineArr, err := transformAggregatePipeline(db.registry, pipeline)
+	if err != nil {
+		return nil, err
+	}
+
+	csOpts := options.MergeChangeStreamOptions(opts...)
+	pipelineDoc, cursorDoc, optsDoc, err := parseOptions(DatabaseStream, csOpts, db.registry)
+	if err != nil {
+		return nil, err
+	}
+	sess, err := getSession(ctx, db.client)
+	if err != nil {
+		return nil, err
+	}
+
+	csDoc := bsonx.Document(bsonx.Doc{
+		{"$changeStream", bsonx.Document(pipelineDoc)},
+	})
+	pipelineArr = append(bsonx.Arr{csDoc}, pipelineArr...)
+
+	cmd := bsonx.Doc{
+		{"aggregate", bsonx.Int32(1)},
+		{"pipeline", bsonx.Array(pipelineArr)},
+		{"cursor", bsonx.Document(cursorDoc)},
+	}
+	cmd = append(cmd, optsDoc...)
+
+	cs := &ChangeStream{
+		client:      db.client,
+		db:          db,
+		sess:        sess,
+		cmd:         cmd,
+		pipeline:    pipelineArr,
+		streamType:  DatabaseStream,
+		readPref:    db.readPreference,
+		readConcern: db.readConcern,
+		options:     csOpts,
+		registry:    db.registry,
+		cursorOpts:  cursorDoc,
+	}
+
+	err = cs.runCommand(ctx, false)
+	if err != nil {
+		return nil, err
+	}
+
+	return cs, nil
+}
+
+func newClientChangeStream(ctx context.Context, client *Client, pipeline interface{},
+	opts ...*options.ChangeStreamOptions) (*ChangeStream, error) {
+
+	pipelineArr, err := transformAggregatePipeline(client.registry, pipeline)
+	if err != nil {
+		return nil, err
+	}
+
+	csOpts := options.MergeChangeStreamOptions(opts...)
+	pipelineDoc, cursorDoc, optsDoc, err := parseOptions(ClientStream, csOpts, client.registry)
+	if err != nil {
+		return nil, err
+	}
+	sess, err := getSession(ctx, client)
+	if err != nil {
+		return nil, err
+	}
+
+	csDoc := bsonx.Document(bsonx.Doc{
+		{"$changeStream", bsonx.Document(pipelineDoc)},
+	})
+	pipelineArr = append(bsonx.Arr{csDoc}, pipelineArr...)
+
+	cmd := bsonx.Doc{
+		{"aggregate", bsonx.Int32(1)},
+		{"pipeline", bsonx.Array(pipelineArr)},
+		{"cursor", bsonx.Document(cursorDoc)},
+	}
+	cmd = append(cmd, optsDoc...)
+
+	cs := &ChangeStream{
+		client:      client,
+		db:          client.Database("admin"),
+		sess:        sess,
+		cmd:         cmd,
+		pipeline:    pipelineArr,
+		streamType:  ClientStream,
+		readPref:    client.readPreference,
+		readConcern: client.readConcern,
+		options:     csOpts,
+		registry:    client.registry,
+		cursorOpts:  cursorDoc,
+	}
+
+	err = cs.runCommand(ctx, false)
+	if err != nil {
+		return nil, err
+	}
+
+	return cs, nil
+}
+
+func (cs *ChangeStream) storeResumeToken() error {
+	idVal, err := cs.cursor.Current.LookupErr("_id")
+	if err != nil {
+		_ = cs.Close(context.Background())
+		return ErrMissingResumeToken
+	}
+
+	var idDoc bson.Raw
+	idDoc, ok := idVal.DocumentOK()
+	if !ok {
+		_ = cs.Close(context.Background())
+		return ErrMissingResumeToken
+	}
+	tokenDoc, err := bsonx.ReadDoc(idDoc)
+	if err != nil {
+		_ = cs.Close(context.Background())
+		return ErrMissingResumeToken
+	}
+
+	cs.resumeToken = tokenDoc
+	return nil
+}
+
+// ID returns the cursor ID for this change stream.
+func (cs *ChangeStream) ID() int64 {
+	if cs.cursor == nil {
+		return 0
+	}
+
+	return cs.cursor.ID()
+}
+
+// Next gets the next result from this change stream. Returns true if there were no errors and the next
+// result is available for decoding.
+func (cs *ChangeStream) Next(ctx context.Context) bool {
+	// execute in a loop to retry resume-able errors and advance the underlying cursor
+	for {
+		if cs.cursor == nil {
+			return false
+		}
+
+		if cs.cursor.Next(ctx) {
+			err := cs.storeResumeToken()
+			if err != nil {
+				cs.err = err
+				return false
+			}
+
+			cs.Current = cs.cursor.Current
+			return true
+		}
+
+		err := cs.cursor.Err()
+		if err == nil {
+			return false
+		}
+
+		switch t := err.(type) {
+		case command.Error:
+			if t.Code == errorInterrupted || t.Code == errorCappedPositionLost || t.Code == errorCursorKilled {
+				return false
+			}
+		}
+
+		killCursors := command.KillCursors{
+			NS:  cs.ns,
+			IDs: []int64{cs.ID()},
+		}
+
+		_, _ = driver.KillCursors(ctx, killCursors, cs.client.topology, cs.db.writeSelector)
+		cs.err = cs.runCommand(ctx, true)
+		if cs.err != nil {
+			return false
+		}
+	}
+}
+
+// Decode will decode the current document into val.
+func (cs *ChangeStream) Decode(out interface{}) error {
+	if cs.cursor == nil {
+		return ErrNilCursor
+	}
+
+	return bson.UnmarshalWithRegistry(cs.registry, cs.Current, out)
+}
+
+// Err returns the current error.
+func (cs *ChangeStream) Err() error {
+	if cs.err != nil {
+		return cs.err
+	}
+	if cs.cursor == nil {
+		return nil
+	}
+
+	return cs.cursor.Err()
+}
+
+// Close closes this cursor.
+func (cs *ChangeStream) Close(ctx context.Context) error {
+	if cs.cursor == nil {
+		return nil // cursor is already closed
+	}
+
+	return cs.cursor.Close(ctx)
+}
+
+// StreamType represents the type of a change stream.
+type StreamType uint8
+
+// These constants represent valid change stream types. A change stream can be initialized over a collection, all
+// collections in a database, or over a whole client.
+const (
+	CollectionStream StreamType = iota
+	DatabaseStream
+	ClientStream
+)
diff --git a/vendor/github.com/mongodb/mongo-go-driver/mongo/client.go b/vendor/github.com/mongodb/mongo-go-driver/mongo/client.go
new file mode 100644
index 0000000..7984bc0
--- /dev/null
+++ b/vendor/github.com/mongodb/mongo-go-driver/mongo/client.go
@@ -0,0 +1,454 @@
+// Copyright (C) MongoDB, Inc. 2017-present.
+//
+// Licensed under the Apache License, Version 2.0 (the "License"); you may
+// not use this file except in compliance with the License. You may obtain
+// a copy of the License at http://www.apache.org/licenses/LICENSE-2.0
+
+package mongo
+
+import (
+	"context"
+	"time"
+
+	"github.com/mongodb/mongo-go-driver/bson"
+	"github.com/mongodb/mongo-go-driver/bson/bsoncodec"
+	"github.com/mongodb/mongo-go-driver/mongo/options"
+	"github.com/mongodb/mongo-go-driver/mongo/readconcern"
+	"github.com/mongodb/mongo-go-driver/mongo/readpref"
+	"github.com/mongodb/mongo-go-driver/mongo/writeconcern"
+	"github.com/mongodb/mongo-go-driver/tag"
+	"github.com/mongodb/mongo-go-driver/x/mongo/driver"
+	"github.com/mongodb/mongo-go-driver/x/mongo/driver/session"
+	"github.com/mongodb/mongo-go-driver/x/mongo/driver/topology"
+	"github.com/mongodb/mongo-go-driver/x/mongo/driver/uuid"
+	"github.com/mongodb/mongo-go-driver/x/network/command"
+	"github.com/mongodb/mongo-go-driver/x/network/connstring"
+	"github.com/mongodb/mongo-go-driver/x/network/description"
+)
+
+const defaultLocalThreshold = 15 * time.Millisecond
+
+// Client performs operations on a given topology.
+type Client struct {
+	id              uuid.UUID
+	topologyOptions []topology.Option
+	topology        *topology.Topology
+	connString      connstring.ConnString
+	localThreshold  time.Duration
+	retryWrites     bool
+	clock           *session.ClusterClock
+	readPreference  *readpref.ReadPref
+	readConcern     *readconcern.ReadConcern
+	writeConcern    *writeconcern.WriteConcern
+	registry        *bsoncodec.Registry
+	marshaller      BSONAppender
+}
+
+// Connect creates a new Client and then initializes it using the Connect method.
+func Connect(ctx context.Context, uri string, opts ...*options.ClientOptions) (*Client, error) {
+	c, err := NewClientWithOptions(uri, opts...)
+	if err != nil {
+		return nil, err
+	}
+	err = c.Connect(ctx)
+	if err != nil {
+		return nil, err
+	}
+	return c, nil
+}
+
+// NewClient creates a new client to connect to a cluster specified by the uri.
+func NewClient(uri string) (*Client, error) {
+	cs, err := connstring.Parse(uri)
+	if err != nil {
+		return nil, err
+	}
+
+	return newClient(cs)
+}
+
+// NewClientWithOptions creates a new client to connect to to a cluster specified by the connection
+// string and the options manually passed in. If the same option is configured in both the
+// connection string and the manual options, the manual option will be ignored.
+func NewClientWithOptions(uri string, opts ...*options.ClientOptions) (*Client, error) {
+	cs, err := connstring.Parse(uri)
+	if err != nil {
+		return nil, err
+	}
+
+	return newClient(cs, opts...)
+}
+
+// Connect initializes the Client by starting background monitoring goroutines.
+// This method must be called before a Client can be used.
+func (c *Client) Connect(ctx context.Context) error {
+	err := c.topology.Connect(ctx)
+	if err != nil {
+		return replaceTopologyErr(err)
+	}
+
+	return nil
+
+}
+
+// Disconnect closes sockets to the topology referenced by this Client. It will
+// shut down any monitoring goroutines, close the idle connection pool, and will
+// wait until all the in use connections have been returned to the connection
+// pool and closed before returning. If the context expires via cancellation,
+// deadline, or timeout before the in use connections have returned, the in use
+// connections will be closed, resulting in the failure of any in flight read
+// or write operations. If this method returns with no errors, all connections
+// associated with this Client have been closed.
+func (c *Client) Disconnect(ctx context.Context) error {
+	c.endSessions(ctx)
+	return replaceTopologyErr(c.topology.Disconnect(ctx))
+}
+
+// Ping verifies that the client can connect to the topology.
+// If readPreference is nil then will use the client's default read
+// preference.
+func (c *Client) Ping(ctx context.Context, rp *readpref.ReadPref) error {
+	if ctx == nil {
+		ctx = context.Background()
+	}
+
+	if rp == nil {
+		rp = c.readPreference
+	}
+
+	_, err := c.topology.SelectServer(ctx, description.ReadPrefSelector(rp))
+	return replaceTopologyErr(err)
+}
+
+// StartSession starts a new session.
+func (c *Client) StartSession(opts ...*options.SessionOptions) (Session, error) {
+	if c.topology.SessionPool == nil {
+		return nil, ErrClientDisconnected
+	}
+
+	sopts := options.MergeSessionOptions(opts...)
+	coreOpts := &session.ClientOptions{
+		DefaultReadConcern:    c.readConcern,
+		DefaultReadPreference: c.readPreference,
+		DefaultWriteConcern:   c.writeConcern,
+	}
+	if sopts.CausalConsistency != nil {
+		coreOpts.CausalConsistency = sopts.CausalConsistency
+	}
+	if sopts.DefaultReadConcern != nil {
+		coreOpts.DefaultReadConcern = sopts.DefaultReadConcern
+	}
+	if sopts.DefaultWriteConcern != nil {
+		coreOpts.DefaultWriteConcern = sopts.DefaultWriteConcern
+	}
+	if sopts.DefaultReadPreference != nil {
+		coreOpts.DefaultReadPreference = sopts.DefaultReadPreference
+	}
+
+	sess, err := session.NewClientSession(c.topology.SessionPool, c.id, session.Explicit, coreOpts)
+	if err != nil {
+		return nil, replaceTopologyErr(err)
+	}
+
+	sess.RetryWrite = c.retryWrites
+
+	return &sessionImpl{
+		Client: sess,
+		topo:   c.topology,
+	}, nil
+}
+
+func (c *Client) endSessions(ctx context.Context) {
+	if c.topology.SessionPool == nil {
+		return
+	}
+	cmd := command.EndSessions{
+		Clock:      c.clock,
+		SessionIDs: c.topology.SessionPool.IDSlice(),
+	}
+
+	_, _ = driver.EndSessions(ctx, cmd, c.topology, description.ReadPrefSelector(readpref.PrimaryPreferred()))
+}
+
+func newClient(cs connstring.ConnString, opts ...*options.ClientOptions) (*Client, error) {
+	clientOpt := options.MergeClientOptions(cs, opts...)
+
+	client := &Client{
+		topologyOptions: clientOpt.TopologyOptions,
+		connString:      clientOpt.ConnString,
+		localThreshold:  defaultLocalThreshold,
+		readPreference:  clientOpt.ReadPreference,
+		readConcern:     clientOpt.ReadConcern,
+		writeConcern:    clientOpt.WriteConcern,
+		registry:        clientOpt.Registry,
+	}
+
+	if client.connString.RetryWritesSet {
+		client.retryWrites = client.connString.RetryWrites
+	}
+	if clientOpt.RetryWrites != nil {
+		client.retryWrites = *clientOpt.RetryWrites
+	}
+
+	clientID, err := uuid.New()
+	if err != nil {
+		return nil, err
+	}
+	client.id = clientID
+
+	topts := append(
+		client.topologyOptions,
+		topology.WithConnString(func(connstring.ConnString) connstring.ConnString { return client.connString }),
+		topology.WithServerOptions(func(opts ...topology.ServerOption) []topology.ServerOption {
+			return append(opts, topology.WithClock(func(clock *session.ClusterClock) *session.ClusterClock {
+				return client.clock
+			}), topology.WithRegistry(func(registry *bsoncodec.Registry) *bsoncodec.Registry {
+				return client.registry
+			}))
+		}),
+	)
+	topo, err := topology.New(topts...)
+	if err != nil {
+		return nil, replaceTopologyErr(err)
+	}
+	client.topology = topo
+	client.clock = &session.ClusterClock{}
+
+	if client.readConcern == nil {
+		client.readConcern = readConcernFromConnString(&client.connString)
+
+		if client.readConcern == nil {
+			// no read concern in conn string
+			client.readConcern = readconcern.New()
+		}
+	}
+
+	if client.writeConcern == nil {
+		client.writeConcern = writeConcernFromConnString(&client.connString)
+	}
+	if client.readPreference == nil {
+		rp, err := readPreferenceFromConnString(&client.connString)
+		if err != nil {
+			return nil, err
+		}
+		if rp != nil {
+			client.readPreference = rp
+		} else {
+			client.readPreference = readpref.Primary()
+		}
+	}
+
+	if client.registry == nil {
+		client.registry = bson.DefaultRegistry
+	}
+	return client, nil
+}
+
+func readConcernFromConnString(cs *connstring.ConnString) *readconcern.ReadConcern {
+	if len(cs.ReadConcernLevel) == 0 {
+		return nil
+	}
+
+	rc := &readconcern.ReadConcern{}
+	readconcern.Level(cs.ReadConcernLevel)(rc)
+
+	return rc
+}
+
+func writeConcernFromConnString(cs *connstring.ConnString) *writeconcern.WriteConcern {
+	var wc *writeconcern.WriteConcern
+
+	if len(cs.WString) > 0 {
+		if wc == nil {
+			wc = writeconcern.New()
+		}
+
+		writeconcern.WTagSet(cs.WString)(wc)
+	} else if cs.WNumberSet {
+		if wc == nil {
+			wc = writeconcern.New()
+		}
+
+		writeconcern.W(cs.WNumber)(wc)
+	}
+
+	if cs.JSet {
+		if wc == nil {
+			wc = writeconcern.New()
+		}
+
+		writeconcern.J(cs.J)(wc)
+	}
+
+	if cs.WTimeoutSet {
+		if wc == nil {
+			wc = writeconcern.New()
+		}
+
+		writeconcern.WTimeout(cs.WTimeout)(wc)
+	}
+
+	return wc
+}
+
+func readPreferenceFromConnString(cs *connstring.ConnString) (*readpref.ReadPref, error) {
+	var rp *readpref.ReadPref
+	var err error
+	options := make([]readpref.Option, 0, 1)
+
+	tagSets := tag.NewTagSetsFromMaps(cs.ReadPreferenceTagSets)
+	if len(tagSets) > 0 {
+		options = append(options, readpref.WithTagSets(tagSets...))
+	}
+
+	if cs.MaxStaleness != 0 {
+		options = append(options, readpref.WithMaxStaleness(cs.MaxStaleness))
+	}
+
+	if len(cs.ReadPreference) > 0 {
+		if rp == nil {
+			mode, _ := readpref.ModeFromString(cs.ReadPreference)
+			rp, err = readpref.New(mode, options...)
+			if err != nil {
+				return nil, err
+			}
+		}
+	}
+
+	return rp, nil
+}
+
+// ValidSession returns an error if the session doesn't belong to the client
+func (c *Client) ValidSession(sess *session.Client) error {
+	if sess != nil && !uuid.Equal(sess.ClientID, c.id) {
+		return ErrWrongClient
+	}
+	return nil
+}
+
+// Database returns a handle for a given database.
+func (c *Client) Database(name string, opts ...*options.DatabaseOptions) *Database {
+	return newDatabase(c, name, opts...)
+}
+
+// ConnectionString returns the connection string of the cluster the client is connected to.
+func (c *Client) ConnectionString() string {
+	return c.connString.Original
+}
+
+// ListDatabases returns a ListDatabasesResult.
+func (c *Client) ListDatabases(ctx context.Context, filter interface{}, opts ...*options.ListDatabasesOptions) (ListDatabasesResult, error) {
+	if ctx == nil {
+		ctx = context.Background()
+	}
+
+	sess := sessionFromContext(ctx)
+
+	err := c.ValidSession(sess)
+	if err != nil {
+		return ListDatabasesResult{}, err
+	}
+
+	f, err := transformDocument(c.registry, filter)
+	if err != nil {
+		return ListDatabasesResult{}, err
+	}
+
+	cmd := command.ListDatabases{
+		Filter:  f,
+		Session: sess,
+		Clock:   c.clock,
+	}
+
+	readSelector := description.CompositeSelector([]description.ServerSelector{
+		description.ReadPrefSelector(readpref.Primary()),
+		description.LatencySelector(c.localThreshold),
+	})
+	res, err := driver.ListDatabases(
+		ctx, cmd,
+		c.topology,
+		readSelector,
+		c.id,
+		c.topology.SessionPool,
+		opts...,
+	)
+	if err != nil {
+		return ListDatabasesResult{}, replaceTopologyErr(err)
+	}
+
+	return (ListDatabasesResult{}).fromResult(res), nil
+}
+
+// ListDatabaseNames returns a slice containing the names of all of the databases on the server.
+func (c *Client) ListDatabaseNames(ctx context.Context, filter interface{}, opts ...*options.ListDatabasesOptions) ([]string, error) {
+	opts = append(opts, options.ListDatabases().SetNameOnly(true))
+
+	res, err := c.ListDatabases(ctx, filter, opts...)
+	if err != nil {
+		return nil, err
+	}
+
+	names := make([]string, 0)
+	for _, spec := range res.Databases {
+		names = append(names, spec.Name)
+	}
+
+	return names, nil
+}
+
+// WithSession allows a user to start a session themselves and manage
+// its lifetime. The only way to provide a session to a CRUD method is
+// to invoke that CRUD method with the mongo.SessionContext within the
+// closure. The mongo.SessionContext can be used as a regular context,
+// so methods like context.WithDeadline and context.WithTimeout are
+// supported.
+//
+// If the context.Context already has a mongo.Session attached, that
+// mongo.Session will be replaced with the one provided.
+//
+// Errors returned from the closure are transparently returned from
+// this function.
+func WithSession(ctx context.Context, sess Session, fn func(SessionContext) error) error {
+	return fn(contextWithSession(ctx, sess))
+}
+
+// UseSession creates a default session, that is only valid for the
+// lifetime of the closure. No cleanup outside of closing the session
+// is done upon exiting the closure. This means that an outstanding
+// transaction will be aborted, even if the closure returns an error.
+//
+// If ctx already contains a mongo.Session, that mongo.Session will be
+// replaced with the newly created mongo.Session.
+//
+// Errors returned from the closure are transparently returned from
+// this method.
+func (c *Client) UseSession(ctx context.Context, fn func(SessionContext) error) error {
+	return c.UseSessionWithOptions(ctx, options.Session(), fn)
+}
+
+// UseSessionWithOptions works like UseSession but allows the caller
+// to specify the options used to create the session.
+func (c *Client) UseSessionWithOptions(ctx context.Context, opts *options.SessionOptions, fn func(SessionContext) error) error {
+	defaultSess, err := c.StartSession(opts)
+	if err != nil {
+		return err
+	}
+
+	defer defaultSess.EndSession(ctx)
+
+	sessCtx := sessionContext{
+		Context: context.WithValue(ctx, sessionKey{}, defaultSess),
+		Session: defaultSess,
+	}
+
+	return fn(sessCtx)
+}
+
+// Watch returns a change stream cursor used to receive information of changes to the client. This method is preferred
+// to running a raw aggregation with a $changeStream stage because it supports resumability in the case of some errors.
+// The client must have read concern majority or no read concern for a change stream to be created successfully.
+func (c *Client) Watch(ctx context.Context, pipeline interface{},
+	opts ...*options.ChangeStreamOptions) (*ChangeStream, error) {
+
+	return newClientChangeStream(ctx, c, pipeline, opts...)
+}
diff --git a/vendor/github.com/mongodb/mongo-go-driver/mongo/collection.go b/vendor/github.com/mongodb/mongo-go-driver/mongo/collection.go
new file mode 100644
index 0000000..fb16775
--- /dev/null
+++ b/vendor/github.com/mongodb/mongo-go-driver/mongo/collection.go
@@ -0,0 +1,1298 @@
+// Copyright (C) MongoDB, Inc. 2017-present.
+//
+// Licensed under the Apache License, Version 2.0 (the "License"); you may
+// not use this file except in compliance with the License. You may obtain
+// a copy of the License at http://www.apache.org/licenses/LICENSE-2.0
+
+package mongo
+
+import (
+	"context"
+	"errors"
+	"strings"
+
+	"github.com/mongodb/mongo-go-driver/bson/bsoncodec"
+	"github.com/mongodb/mongo-go-driver/mongo/options"
+	"github.com/mongodb/mongo-go-driver/mongo/readconcern"
+	"github.com/mongodb/mongo-go-driver/mongo/readpref"
+	"github.com/mongodb/mongo-go-driver/mongo/writeconcern"
+	"github.com/mongodb/mongo-go-driver/x/bsonx"
+	"github.com/mongodb/mongo-go-driver/x/mongo/driver"
+	"github.com/mongodb/mongo-go-driver/x/mongo/driver/session"
+	"github.com/mongodb/mongo-go-driver/x/network/command"
+	"github.com/mongodb/mongo-go-driver/x/network/description"
+)
+
+// Collection performs operations on a given collection.
+type Collection struct {
+	client         *Client
+	db             *Database
+	name           string
+	readConcern    *readconcern.ReadConcern
+	writeConcern   *writeconcern.WriteConcern
+	readPreference *readpref.ReadPref
+	readSelector   description.ServerSelector
+	writeSelector  description.ServerSelector
+	registry       *bsoncodec.Registry
+}
+
+func newCollection(db *Database, name string, opts ...*options.CollectionOptions) *Collection {
+	collOpt := options.MergeCollectionOptions(opts...)
+
+	rc := db.readConcern
+	if collOpt.ReadConcern != nil {
+		rc = collOpt.ReadConcern
+	}
+
+	wc := db.writeConcern
+	if collOpt.WriteConcern != nil {
+		wc = collOpt.WriteConcern
+	}
+
+	rp := db.readPreference
+	if collOpt.ReadPreference != nil {
+		rp = collOpt.ReadPreference
+	}
+
+	reg := db.registry
+	if collOpt.Registry != nil {
+		reg = collOpt.Registry
+	}
+
+	readSelector := description.CompositeSelector([]description.ServerSelector{
+		description.ReadPrefSelector(rp),
+		description.LatencySelector(db.client.localThreshold),
+	})
+
+	writeSelector := description.CompositeSelector([]description.ServerSelector{
+		description.WriteSelector(),
+		description.LatencySelector(db.client.localThreshold),
+	})
+
+	coll := &Collection{
+		client:         db.client,
+		db:             db,
+		name:           name,
+		readPreference: rp,
+		readConcern:    rc,
+		writeConcern:   wc,
+		readSelector:   readSelector,
+		writeSelector:  writeSelector,
+		registry:       reg,
+	}
+
+	return coll
+}
+
+func (coll *Collection) copy() *Collection {
+	return &Collection{
+		client:         coll.client,
+		db:             coll.db,
+		name:           coll.name,
+		readConcern:    coll.readConcern,
+		writeConcern:   coll.writeConcern,
+		readPreference: coll.readPreference,
+		readSelector:   coll.readSelector,
+		writeSelector:  coll.writeSelector,
+		registry:       coll.registry,
+	}
+}
+
+// Clone creates a copy of this collection with updated options, if any are given.
+func (coll *Collection) Clone(opts ...*options.CollectionOptions) (*Collection, error) {
+	copyColl := coll.copy()
+	optsColl := options.MergeCollectionOptions(opts...)
+
+	if optsColl.ReadConcern != nil {
+		copyColl.readConcern = optsColl.ReadConcern
+	}
+
+	if optsColl.WriteConcern != nil {
+		copyColl.writeConcern = optsColl.WriteConcern
+	}
+
+	if optsColl.ReadPreference != nil {
+		copyColl.readPreference = optsColl.ReadPreference
+	}
+
+	if optsColl.Registry != nil {
+		copyColl.registry = optsColl.Registry
+	}
+
+	copyColl.readSelector = description.CompositeSelector([]description.ServerSelector{
+		description.ReadPrefSelector(copyColl.readPreference),
+		description.LatencySelector(copyColl.client.localThreshold),
+	})
+
+	return copyColl, nil
+}
+
+// Name provides access to the name of the collection.
+func (coll *Collection) Name() string {
+	return coll.name
+}
+
+// namespace returns the namespace of the collection.
+func (coll *Collection) namespace() command.Namespace {
+	return command.NewNamespace(coll.db.name, coll.name)
+}
+
+// Database provides access to the database that contains the collection.
+func (coll *Collection) Database() *Database {
+	return coll.db
+}
+
+// BulkWrite performs a bulk write operation.
+//
+// See https://docs.mongodb.com/manual/core/bulk-write-operations/.
+func (coll *Collection) BulkWrite(ctx context.Context, models []WriteModel,
+	opts ...*options.BulkWriteOptions) (*BulkWriteResult, error) {
+
+	if len(models) == 0 {
+		return nil, ErrEmptySlice
+	}
+
+	if ctx == nil {
+		ctx = context.Background()
+	}
+
+	sess := sessionFromContext(ctx)
+
+	err := coll.client.ValidSession(sess)
+	if err != nil {
+		return nil, err
+	}
+
+	dispatchModels := make([]driver.WriteModel, len(models))
+	for i, model := range models {
+		if model == nil {
+			return nil, ErrNilDocument
+		}
+		dispatchModels[i] = model.convertModel()
+	}
+
+	res, err := driver.BulkWrite(
+		ctx,
+		coll.namespace(),
+		dispatchModels,
+		coll.client.topology,
+		coll.writeSelector,
+		coll.client.id,
+		coll.client.topology.SessionPool,
+		coll.client.retryWrites,
+		sess,
+		coll.writeConcern,
+		coll.client.clock,
+		coll.registry,
+		opts...,
+	)
+
+	if err != nil {
+		if conv, ok := err.(driver.BulkWriteException); ok {
+			return &BulkWriteResult{}, BulkWriteException{
+				WriteConcernError: convertWriteConcernError(conv.WriteConcernError),
+				WriteErrors:       convertBulkWriteErrors(conv.WriteErrors),
+			}
+		}
+
+		return &BulkWriteResult{}, replaceTopologyErr(err)
+	}
+
+	return &BulkWriteResult{
+		InsertedCount: res.InsertedCount,
+		MatchedCount:  res.MatchedCount,
+		ModifiedCount: res.ModifiedCount,
+		DeletedCount:  res.DeletedCount,
+		UpsertedCount: res.UpsertedCount,
+		UpsertedIDs:   res.UpsertedIDs,
+	}, nil
+}
+
+// InsertOne inserts a single document into the collection.
+func (coll *Collection) InsertOne(ctx context.Context, document interface{},
+	opts ...*options.InsertOneOptions) (*InsertOneResult, error) {
+
+	if ctx == nil {
+		ctx = context.Background()
+	}
+
+	doc, insertedID, err := transformAndEnsureID(coll.registry, document)
+	if err != nil {
+		return nil, err
+	}
+
+	sess := sessionFromContext(ctx)
+
+	err = coll.client.ValidSession(sess)
+	if err != nil {
+		return nil, err
+	}
+
+	wc := coll.writeConcern
+	if sess != nil && sess.TransactionRunning() {
+		wc = nil
+	}
+	oldns := coll.namespace()
+	cmd := command.Insert{
+		NS:           command.Namespace{DB: oldns.DB, Collection: oldns.Collection},
+		Docs:         []bsonx.Doc{doc},
+		WriteConcern: wc,
+		Session:      sess,
+		Clock:        coll.client.clock,
+	}
+
+	// convert to InsertManyOptions so these can be argued to dispatch.Insert
+	insertOpts := make([]*options.InsertManyOptions, len(opts))
+	for i, opt := range opts {
+		insertOpts[i] = options.InsertMany()
+		insertOpts[i].BypassDocumentValidation = opt.BypassDocumentValidation
+	}
+
+	res, err := driver.Insert(
+		ctx, cmd,
+		coll.client.topology,
+		coll.writeSelector,
+		coll.client.id,
+		coll.client.topology.SessionPool,
+		coll.client.retryWrites,
+		insertOpts...,
+	)
+
+	rr, err := processWriteError(res.WriteConcernError, res.WriteErrors, err)
+	if rr&rrOne == 0 {
+		return nil, err
+	}
+
+	return &InsertOneResult{InsertedID: insertedID}, err
+}
+
+// InsertMany inserts the provided documents.
+func (coll *Collection) InsertMany(ctx context.Context, documents []interface{},
+	opts ...*options.InsertManyOptions) (*InsertManyResult, error) {
+
+	if ctx == nil {
+		ctx = context.Background()
+	}
+
+	if len(documents) == 0 {
+		return nil, ErrEmptySlice
+	}
+
+	result := make([]interface{}, len(documents))
+	docs := make([]bsonx.Doc, len(documents))
+
+	for i, doc := range documents {
+		if doc == nil {
+			return nil, ErrNilDocument
+		}
+		bdoc, insertedID, err := transformAndEnsureID(coll.registry, doc)
+		if err != nil {
+			return nil, err
+		}
+
+		docs[i] = bdoc
+		result[i] = insertedID
+	}
+
+	sess := sessionFromContext(ctx)
+
+	err := coll.client.ValidSession(sess)
+	if err != nil {
+		return nil, err
+	}
+
+	wc := coll.writeConcern
+	if sess != nil && sess.TransactionRunning() {
+		wc = nil
+	}
+
+	oldns := coll.namespace()
+	cmd := command.Insert{
+		NS:           command.Namespace{DB: oldns.DB, Collection: oldns.Collection},
+		Docs:         docs,
+		WriteConcern: wc,
+		Session:      sess,
+		Clock:        coll.client.clock,
+	}
+
+	res, err := driver.Insert(
+		ctx, cmd,
+		coll.client.topology,
+		coll.writeSelector,
+		coll.client.id,
+		coll.client.topology.SessionPool,
+		coll.client.retryWrites,
+		opts...,
+	)
+
+	switch err {
+	case nil:
+	case command.ErrUnacknowledgedWrite:
+		return &InsertManyResult{InsertedIDs: result}, ErrUnacknowledgedWrite
+	default:
+		return nil, replaceTopologyErr(err)
+	}
+	if len(res.WriteErrors) > 0 || res.WriteConcernError != nil {
+		bwErrors := make([]BulkWriteError, 0, len(res.WriteErrors))
+		for _, we := range res.WriteErrors {
+			bwErrors = append(bwErrors, BulkWriteError{
+				WriteError{
+					Index:   we.Index,
+					Code:    we.Code,
+					Message: we.ErrMsg,
+				},
+				nil,
+			})
+		}
+
+		err = BulkWriteException{
+			WriteErrors:       bwErrors,
+			WriteConcernError: convertWriteConcernError(res.WriteConcernError),
+		}
+	}
+
+	return &InsertManyResult{InsertedIDs: result}, err
+}
+
+// DeleteOne deletes a single document from the collection.
+func (coll *Collection) DeleteOne(ctx context.Context, filter interface{},
+	opts ...*options.DeleteOptions) (*DeleteResult, error) {
+
+	if ctx == nil {
+		ctx = context.Background()
+	}
+
+	f, err := transformDocument(coll.registry, filter)
+	if err != nil {
+		return nil, err
+	}
+	deleteDocs := []bsonx.Doc{
+		{
+			{"q", bsonx.Document(f)},
+			{"limit", bsonx.Int32(1)},
+		},
+	}
+
+	sess := sessionFromContext(ctx)
+
+	err = coll.client.ValidSession(sess)
+	if err != nil {
+		return nil, err
+	}
+
+	wc := coll.writeConcern
+	if sess != nil && sess.TransactionRunning() {
+		wc = nil
+	}
+
+	oldns := coll.namespace()
+	cmd := command.Delete{
+		NS:           command.Namespace{DB: oldns.DB, Collection: oldns.Collection},
+		Deletes:      deleteDocs,
+		WriteConcern: wc,
+		Session:      sess,
+		Clock:        coll.client.clock,
+	}
+
+	res, err := driver.Delete(
+		ctx, cmd,
+		coll.client.topology,
+		coll.writeSelector,
+		coll.client.id,
+		coll.client.topology.SessionPool,
+		coll.client.retryWrites,
+		opts...,
+	)
+
+	rr, err := processWriteError(res.WriteConcernError, res.WriteErrors, err)
+	if rr&rrOne == 0 {
+		return nil, err
+	}
+	return &DeleteResult{DeletedCount: int64(res.N)}, err
+}
+
+// DeleteMany deletes multiple documents from the collection.
+func (coll *Collection) DeleteMany(ctx context.Context, filter interface{},
+	opts ...*options.DeleteOptions) (*DeleteResult, error) {
+
+	if ctx == nil {
+		ctx = context.Background()
+	}
+
+	f, err := transformDocument(coll.registry, filter)
+	if err != nil {
+		return nil, err
+	}
+	deleteDocs := []bsonx.Doc{{{"q", bsonx.Document(f)}, {"limit", bsonx.Int32(0)}}}
+
+	sess := sessionFromContext(ctx)
+
+	err = coll.client.ValidSession(sess)
+	if err != nil {
+		return nil, err
+	}
+
+	wc := coll.writeConcern
+	if sess != nil && sess.TransactionRunning() {
+		wc = nil
+	}
+
+	oldns := coll.namespace()
+	cmd := command.Delete{
+		NS:           command.Namespace{DB: oldns.DB, Collection: oldns.Collection},
+		Deletes:      deleteDocs,
+		WriteConcern: wc,
+		Session:      sess,
+		Clock:        coll.client.clock,
+	}
+
+	res, err := driver.Delete(
+		ctx, cmd,
+		coll.client.topology,
+		coll.writeSelector,
+		coll.client.id,
+		coll.client.topology.SessionPool,
+		false,
+		opts...,
+	)
+
+	rr, err := processWriteError(res.WriteConcernError, res.WriteErrors, err)
+	if rr&rrMany == 0 {
+		return nil, err
+	}
+	return &DeleteResult{DeletedCount: int64(res.N)}, err
+}
+
+func (coll *Collection) updateOrReplaceOne(ctx context.Context, filter,
+	update bsonx.Doc, sess *session.Client, opts ...*options.UpdateOptions) (*UpdateResult, error) {
+
+	// TODO: should session be taken from ctx or left as argument?
+	if ctx == nil {
+		ctx = context.Background()
+	}
+
+	updateDocs := []bsonx.Doc{
+		{
+			{"q", bsonx.Document(filter)},
+			{"u", bsonx.Document(update)},
+			{"multi", bsonx.Boolean(false)},
+		},
+	}
+
+	wc := coll.writeConcern
+	if sess != nil && sess.TransactionRunning() {
+		wc = nil
+	}
+
+	oldns := coll.namespace()
+	cmd := command.Update{
+		NS:           command.Namespace{DB: oldns.DB, Collection: oldns.Collection},
+		Docs:         updateDocs,
+		WriteConcern: wc,
+		Session:      sess,
+		Clock:        coll.client.clock,
+	}
+
+	r, err := driver.Update(
+		ctx, cmd,
+		coll.client.topology,
+		coll.writeSelector,
+		coll.client.id,
+		coll.client.topology.SessionPool,
+		coll.client.retryWrites,
+		opts...,
+	)
+	if err != nil && err != command.ErrUnacknowledgedWrite {
+		return nil, replaceTopologyErr(err)
+	}
+
+	res := &UpdateResult{
+		MatchedCount:  r.MatchedCount,
+		ModifiedCount: r.ModifiedCount,
+		UpsertedCount: int64(len(r.Upserted)),
+	}
+	if len(r.Upserted) > 0 {
+		res.UpsertedID = r.Upserted[0].ID
+		res.MatchedCount--
+	}
+
+	rr, err := processWriteError(r.WriteConcernError, r.WriteErrors, err)
+	if rr&rrOne == 0 {
+		return nil, err
+	}
+	return res, err
+}
+
+// UpdateOne updates a single document in the collection.
+func (coll *Collection) UpdateOne(ctx context.Context, filter interface{}, update interface{},
+	opts ...*options.UpdateOptions) (*UpdateResult, error) {
+
+	if ctx == nil {
+		ctx = context.Background()
+	}
+
+	f, err := transformDocument(coll.registry, filter)
+	if err != nil {
+		return nil, err
+	}
+
+	u, err := transformDocument(coll.registry, update)
+	if err != nil {
+		return nil, err
+	}
+
+	if err := ensureDollarKey(u); err != nil {
+		return nil, err
+	}
+
+	sess := sessionFromContext(ctx)
+
+	err = coll.client.ValidSession(sess)
+	if err != nil {
+		return nil, err
+	}
+
+	return coll.updateOrReplaceOne(ctx, f, u, sess, opts...)
+}
+
+// UpdateMany updates multiple documents in the collection.
+func (coll *Collection) UpdateMany(ctx context.Context, filter interface{}, update interface{},
+	opts ...*options.UpdateOptions) (*UpdateResult, error) {
+
+	if ctx == nil {
+		ctx = context.Background()
+	}
+
+	f, err := transformDocument(coll.registry, filter)
+	if err != nil {
+		return nil, err
+	}
+
+	u, err := transformDocument(coll.registry, update)
+	if err != nil {
+		return nil, err
+	}
+
+	if err = ensureDollarKey(u); err != nil {
+		return nil, err
+	}
+
+	updateDocs := []bsonx.Doc{
+		{
+			{"q", bsonx.Document(f)},
+			{"u", bsonx.Document(u)},
+			{"multi", bsonx.Boolean(true)},
+		},
+	}
+
+	sess := sessionFromContext(ctx)
+
+	err = coll.client.ValidSession(sess)
+	if err != nil {
+		return nil, err
+	}
+
+	wc := coll.writeConcern
+	if sess != nil && sess.TransactionRunning() {
+		wc = nil
+	}
+
+	oldns := coll.namespace()
+	cmd := command.Update{
+		NS:           command.Namespace{DB: oldns.DB, Collection: oldns.Collection},
+		Docs:         updateDocs,
+		WriteConcern: wc,
+		Session:      sess,
+		Clock:        coll.client.clock,
+	}
+
+	r, err := driver.Update(
+		ctx, cmd,
+		coll.client.topology,
+		coll.writeSelector,
+		coll.client.id,
+		coll.client.topology.SessionPool,
+		false,
+		opts...,
+	)
+	if err != nil && err != command.ErrUnacknowledgedWrite {
+		return nil, replaceTopologyErr(err)
+	}
+	res := &UpdateResult{
+		MatchedCount:  r.MatchedCount,
+		ModifiedCount: r.ModifiedCount,
+		UpsertedCount: int64(len(r.Upserted)),
+	}
+	// TODO(skriptble): Is this correct? Do we only return the first upserted ID for an UpdateMany?
+	if len(r.Upserted) > 0 {
+		res.UpsertedID = r.Upserted[0].ID
+		res.MatchedCount--
+	}
+
+	rr, err := processWriteError(r.WriteConcernError, r.WriteErrors, err)
+	if rr&rrMany == 0 {
+		return nil, err
+	}
+	return res, err
+}
+
+// ReplaceOne replaces a single document in the collection.
+func (coll *Collection) ReplaceOne(ctx context.Context, filter interface{},
+	replacement interface{}, opts ...*options.ReplaceOptions) (*UpdateResult, error) {
+
+	if ctx == nil {
+		ctx = context.Background()
+	}
+
+	f, err := transformDocument(coll.registry, filter)
+	if err != nil {
+		return nil, err
+	}
+
+	r, err := transformDocument(coll.registry, replacement)
+	if err != nil {
+		return nil, err
+	}
+
+	if len(r) > 0 && strings.HasPrefix(r[0].Key, "$") {
+		return nil, errors.New("replacement document cannot contains keys beginning with '$")
+	}
+
+	sess := sessionFromContext(ctx)
+
+	err = coll.client.ValidSession(sess)
+	if err != nil {
+		return nil, err
+	}
+
+	updateOptions := make([]*options.UpdateOptions, 0, len(opts))
+	for _, opt := range opts {
+		uOpts := options.Update()
+		uOpts.BypassDocumentValidation = opt.BypassDocumentValidation
+		uOpts.Collation = opt.Collation
+		uOpts.Upsert = opt.Upsert
+		updateOptions = append(updateOptions, uOpts)
+	}
+
+	return coll.updateOrReplaceOne(ctx, f, r, sess, updateOptions...)
+}
+
+// Aggregate runs an aggregation framework pipeline.
+//
+// See https://docs.mongodb.com/manual/aggregation/.
+func (coll *Collection) Aggregate(ctx context.Context, pipeline interface{},
+	opts ...*options.AggregateOptions) (*Cursor, error) {
+
+	if ctx == nil {
+		ctx = context.Background()
+	}
+
+	pipelineArr, err := transformAggregatePipeline(coll.registry, pipeline)
+	if err != nil {
+		return nil, err
+	}
+
+	aggOpts := options.MergeAggregateOptions(opts...)
+
+	sess := sessionFromContext(ctx)
+
+	err = coll.client.ValidSession(sess)
+	if err != nil {
+		return nil, err
+	}
+
+	wc := coll.writeConcern
+	if sess != nil && sess.TransactionRunning() {
+		wc = nil
+	}
+
+	rc := coll.readConcern
+	if sess != nil && (sess.TransactionInProgress()) {
+		rc = nil
+	}
+
+	oldns := coll.namespace()
+	cmd := command.Aggregate{
+		NS:           command.Namespace{DB: oldns.DB, Collection: oldns.Collection},
+		Pipeline:     pipelineArr,
+		ReadPref:     coll.readPreference,
+		WriteConcern: wc,
+		ReadConcern:  rc,
+		Session:      sess,
+		Clock:        coll.client.clock,
+	}
+
+	batchCursor, err := driver.Aggregate(
+		ctx, cmd,
+		coll.client.topology,
+		coll.readSelector,
+		coll.writeSelector,
+		coll.client.id,
+		coll.client.topology.SessionPool,
+		coll.registry,
+		aggOpts,
+	)
+	if err != nil {
+		return nil, replaceTopologyErr(err)
+	}
+
+	cursor, err := newCursor(batchCursor, coll.registry)
+	return cursor, replaceTopologyErr(err)
+}
+
+// Count gets the number of documents matching the filter.
+func (coll *Collection) Count(ctx context.Context, filter interface{},
+	opts ...*options.CountOptions) (int64, error) {
+
+	if ctx == nil {
+		ctx = context.Background()
+	}
+
+	f, err := transformDocument(coll.registry, filter)
+	if err != nil {
+		return 0, err
+	}
+
+	sess := sessionFromContext(ctx)
+
+	err = coll.client.ValidSession(sess)
+	if err != nil {
+		return 0, err
+	}
+
+	rc := coll.readConcern
+	if sess != nil && (sess.TransactionInProgress()) {
+		rc = nil
+	}
+
+	oldns := coll.namespace()
+	cmd := command.Count{
+		NS:          command.Namespace{DB: oldns.DB, Collection: oldns.Collection},
+		Query:       f,
+		ReadPref:    coll.readPreference,
+		ReadConcern: rc,
+		Session:     sess,
+		Clock:       coll.client.clock,
+	}
+
+	count, err := driver.Count(
+		ctx, cmd,
+		coll.client.topology,
+		coll.readSelector,
+		coll.client.id,
+		coll.client.topology.SessionPool,
+		coll.registry,
+		opts...,
+	)
+
+	return count, replaceTopologyErr(err)
+}
+
+// CountDocuments gets the number of documents matching the filter.
+func (coll *Collection) CountDocuments(ctx context.Context, filter interface{},
+	opts ...*options.CountOptions) (int64, error) {
+
+	if ctx == nil {
+		ctx = context.Background()
+	}
+
+	countOpts := options.MergeCountOptions(opts...)
+
+	pipelineArr, err := countDocumentsAggregatePipeline(coll.registry, filter, countOpts)
+	if err != nil {
+		return 0, err
+	}
+
+	sess := sessionFromContext(ctx)
+
+	err = coll.client.ValidSession(sess)
+	if err != nil {
+		return 0, err
+	}
+
+	rc := coll.readConcern
+	if sess != nil && (sess.TransactionInProgress()) {
+		rc = nil
+	}
+
+	oldns := coll.namespace()
+	cmd := command.CountDocuments{
+		NS:          command.Namespace{DB: oldns.DB, Collection: oldns.Collection},
+		Pipeline:    pipelineArr,
+		ReadPref:    coll.readPreference,
+		ReadConcern: rc,
+		Session:     sess,
+		Clock:       coll.client.clock,
+	}
+
+	count, err := driver.CountDocuments(
+		ctx, cmd,
+		coll.client.topology,
+		coll.readSelector,
+		coll.client.id,
+		coll.client.topology.SessionPool,
+		coll.registry,
+		countOpts,
+	)
+
+	return count, replaceTopologyErr(err)
+}
+
+// EstimatedDocumentCount gets an estimate of the count of documents in a collection using collection metadata.
+func (coll *Collection) EstimatedDocumentCount(ctx context.Context,
+	opts ...*options.EstimatedDocumentCountOptions) (int64, error) {
+
+	if ctx == nil {
+		ctx = context.Background()
+	}
+
+	sess := sessionFromContext(ctx)
+
+	err := coll.client.ValidSession(sess)
+	if err != nil {
+		return 0, err
+	}
+
+	rc := coll.readConcern
+	if sess != nil && (sess.TransactionInProgress()) {
+		rc = nil
+	}
+
+	oldns := coll.namespace()
+	cmd := command.Count{
+		NS:          command.Namespace{DB: oldns.DB, Collection: oldns.Collection},
+		Query:       bsonx.Doc{},
+		ReadPref:    coll.readPreference,
+		ReadConcern: rc,
+		Session:     sess,
+		Clock:       coll.client.clock,
+	}
+
+	countOpts := options.Count()
+	if len(opts) >= 1 {
+		countOpts = countOpts.SetMaxTime(*opts[len(opts)-1].MaxTime)
+	}
+
+	count, err := driver.Count(
+		ctx, cmd,
+		coll.client.topology,
+		coll.readSelector,
+		coll.client.id,
+		coll.client.topology.SessionPool,
+		coll.registry,
+		countOpts,
+	)
+
+	return count, replaceTopologyErr(err)
+}
+
+// Distinct finds the distinct values for a specified field across a single
+// collection.
+func (coll *Collection) Distinct(ctx context.Context, fieldName string, filter interface{},
+	opts ...*options.DistinctOptions) ([]interface{}, error) {
+
+	if ctx == nil {
+		ctx = context.Background()
+	}
+
+	f, err := transformDocument(coll.registry, filter)
+	if err != nil {
+		return nil, err
+	}
+
+	sess := sessionFromContext(ctx)
+
+	err = coll.client.ValidSession(sess)
+	if err != nil {
+		return nil, err
+	}
+
+	rc := coll.readConcern
+	if sess != nil && (sess.TransactionInProgress()) {
+		rc = nil
+	}
+
+	oldns := coll.namespace()
+	cmd := command.Distinct{
+		NS:          command.Namespace{DB: oldns.DB, Collection: oldns.Collection},
+		Field:       fieldName,
+		Query:       f,
+		ReadPref:    coll.readPreference,
+		ReadConcern: rc,
+		Session:     sess,
+		Clock:       coll.client.clock,
+	}
+
+	res, err := driver.Distinct(
+		ctx, cmd,
+		coll.client.topology,
+		coll.readSelector,
+		coll.client.id,
+		coll.client.topology.SessionPool,
+		opts...,
+	)
+	if err != nil {
+		return nil, replaceTopologyErr(err)
+	}
+
+	return res.Values, nil
+}
+
+// Find finds the documents matching a model.
+func (coll *Collection) Find(ctx context.Context, filter interface{},
+	opts ...*options.FindOptions) (*Cursor, error) {
+
+	if ctx == nil {
+		ctx = context.Background()
+	}
+
+	f, err := transformDocument(coll.registry, filter)
+	if err != nil {
+		return nil, err
+	}
+
+	sess := sessionFromContext(ctx)
+
+	err = coll.client.ValidSession(sess)
+	if err != nil {
+		return nil, err
+	}
+
+	rc := coll.readConcern
+	if sess != nil && (sess.TransactionInProgress()) {
+		rc = nil
+	}
+
+	oldns := coll.namespace()
+	cmd := command.Find{
+		NS:          command.Namespace{DB: oldns.DB, Collection: oldns.Collection},
+		Filter:      f,
+		ReadPref:    coll.readPreference,
+		ReadConcern: rc,
+		Session:     sess,
+		Clock:       coll.client.clock,
+	}
+
+	batchCursor, err := driver.Find(
+		ctx, cmd,
+		coll.client.topology,
+		coll.readSelector,
+		coll.client.id,
+		coll.client.topology.SessionPool,
+		coll.registry,
+		opts...,
+	)
+	if err != nil {
+		return nil, replaceTopologyErr(err)
+	}
+
+	cursor, err := newCursor(batchCursor, coll.registry)
+	return cursor, replaceTopologyErr(err)
+}
+
+// FindOne returns up to one document that matches the model.
+func (coll *Collection) FindOne(ctx context.Context, filter interface{},
+	opts ...*options.FindOneOptions) *SingleResult {
+
+	if ctx == nil {
+		ctx = context.Background()
+	}
+
+	f, err := transformDocument(coll.registry, filter)
+	if err != nil {
+		return &SingleResult{err: err}
+	}
+
+	sess := sessionFromContext(ctx)
+
+	err = coll.client.ValidSession(sess)
+	if err != nil {
+		return &SingleResult{err: err}
+	}
+
+	rc := coll.readConcern
+	if sess != nil && (sess.TransactionInProgress()) {
+		rc = nil
+	}
+
+	oldns := coll.namespace()
+	cmd := command.Find{
+		NS:          command.Namespace{DB: oldns.DB, Collection: oldns.Collection},
+		Filter:      f,
+		ReadPref:    coll.readPreference,
+		ReadConcern: rc,
+		Session:     sess,
+		Clock:       coll.client.clock,
+	}
+
+	findOpts := make([]*options.FindOptions, len(opts))
+	for i, opt := range opts {
+		findOpts[i] = &options.FindOptions{
+			AllowPartialResults: opt.AllowPartialResults,
+			BatchSize:           opt.BatchSize,
+			Collation:           opt.Collation,
+			Comment:             opt.Comment,
+			CursorType:          opt.CursorType,
+			Hint:                opt.Hint,
+			Max:                 opt.Max,
+			MaxAwaitTime:        opt.MaxAwaitTime,
+			Min:                 opt.Min,
+			NoCursorTimeout:     opt.NoCursorTimeout,
+			OplogReplay:         opt.OplogReplay,
+			Projection:          opt.Projection,
+			ReturnKey:           opt.ReturnKey,
+			ShowRecordID:        opt.ShowRecordID,
+			Skip:                opt.Skip,
+			Snapshot:            opt.Snapshot,
+			Sort:                opt.Sort,
+		}
+	}
+
+	batchCursor, err := driver.Find(
+		ctx, cmd,
+		coll.client.topology,
+		coll.readSelector,
+		coll.client.id,
+		coll.client.topology.SessionPool,
+		coll.registry,
+		findOpts...,
+	)
+	if err != nil {
+		return &SingleResult{err: replaceTopologyErr(err)}
+	}
+
+	cursor, err := newCursor(batchCursor, coll.registry)
+	return &SingleResult{cur: cursor, reg: coll.registry, err: replaceTopologyErr(err)}
+}
+
+// FindOneAndDelete find a single document and deletes it, returning the
+// original in result.
+func (coll *Collection) FindOneAndDelete(ctx context.Context, filter interface{},
+	opts ...*options.FindOneAndDeleteOptions) *SingleResult {
+
+	if ctx == nil {
+		ctx = context.Background()
+	}
+
+	f, err := transformDocument(coll.registry, filter)
+	if err != nil {
+		return &SingleResult{err: err}
+	}
+
+	sess := sessionFromContext(ctx)
+
+	err = coll.client.ValidSession(sess)
+	if err != nil {
+		return &SingleResult{err: err}
+	}
+
+	oldns := coll.namespace()
+	wc := coll.writeConcern
+	if sess != nil && sess.TransactionRunning() {
+		wc = nil
+	}
+
+	cmd := command.FindOneAndDelete{
+		NS:           command.Namespace{DB: oldns.DB, Collection: oldns.Collection},
+		Query:        f,
+		WriteConcern: wc,
+		Session:      sess,
+		Clock:        coll.client.clock,
+	}
+
+	res, err := driver.FindOneAndDelete(
+		ctx, cmd,
+		coll.client.topology,
+		coll.writeSelector,
+		coll.client.id,
+		coll.client.topology.SessionPool,
+		coll.client.retryWrites,
+		coll.registry,
+		opts...,
+	)
+	if err != nil {
+		return &SingleResult{err: replaceTopologyErr(err)}
+	}
+
+	return &SingleResult{rdr: res.Value, reg: coll.registry}
+}
+
+// FindOneAndReplace finds a single document and replaces it, returning either
+// the original or the replaced document.
+func (coll *Collection) FindOneAndReplace(ctx context.Context, filter interface{},
+	replacement interface{}, opts ...*options.FindOneAndReplaceOptions) *SingleResult {
+
+	if ctx == nil {
+		ctx = context.Background()
+	}
+
+	f, err := transformDocument(coll.registry, filter)
+	if err != nil {
+		return &SingleResult{err: err}
+	}
+
+	r, err := transformDocument(coll.registry, replacement)
+	if err != nil {
+		return &SingleResult{err: err}
+	}
+
+	if len(r) > 0 && strings.HasPrefix(r[0].Key, "$") {
+		return &SingleResult{err: errors.New("replacement document cannot contains keys beginning with '$")}
+	}
+
+	sess := sessionFromContext(ctx)
+
+	err = coll.client.ValidSession(sess)
+	if err != nil {
+		return &SingleResult{err: err}
+	}
+
+	wc := coll.writeConcern
+	if sess != nil && sess.TransactionRunning() {
+		wc = nil
+	}
+
+	oldns := coll.namespace()
+	cmd := command.FindOneAndReplace{
+		NS:           command.Namespace{DB: oldns.DB, Collection: oldns.Collection},
+		Query:        f,
+		Replacement:  r,
+		WriteConcern: wc,
+		Session:      sess,
+		Clock:        coll.client.clock,
+	}
+
+	res, err := driver.FindOneAndReplace(
+		ctx, cmd,
+		coll.client.topology,
+		coll.writeSelector,
+		coll.client.id,
+		coll.client.topology.SessionPool,
+		coll.client.retryWrites,
+		coll.registry,
+		opts...,
+	)
+	if err != nil {
+		return &SingleResult{err: replaceTopologyErr(err)}
+	}
+
+	return &SingleResult{rdr: res.Value, reg: coll.registry}
+}
+
+// FindOneAndUpdate finds a single document and updates it, returning either
+// the original or the updated.
+func (coll *Collection) FindOneAndUpdate(ctx context.Context, filter interface{},
+	update interface{}, opts ...*options.FindOneAndUpdateOptions) *SingleResult {
+
+	if ctx == nil {
+		ctx = context.Background()
+	}
+
+	f, err := transformDocument(coll.registry, filter)
+	if err != nil {
+		return &SingleResult{err: err}
+	}
+
+	u, err := transformDocument(coll.registry, update)
+	if err != nil {
+		return &SingleResult{err: err}
+	}
+
+	err = ensureDollarKey(u)
+	if err != nil {
+		return &SingleResult{
+			err: err,
+		}
+	}
+
+	sess := sessionFromContext(ctx)
+
+	err = coll.client.ValidSession(sess)
+	if err != nil {
+		return &SingleResult{err: err}
+	}
+
+	wc := coll.writeConcern
+	if sess != nil && sess.TransactionRunning() {
+		wc = nil
+	}
+
+	oldns := coll.namespace()
+	cmd := command.FindOneAndUpdate{
+		NS:           command.Namespace{DB: oldns.DB, Collection: oldns.Collection},
+		Query:        f,
+		Update:       u,
+		WriteConcern: wc,
+		Session:      sess,
+		Clock:        coll.client.clock,
+	}
+
+	res, err := driver.FindOneAndUpdate(
+		ctx, cmd,
+		coll.client.topology,
+		coll.writeSelector,
+		coll.client.id,
+		coll.client.topology.SessionPool,
+		coll.client.retryWrites,
+		coll.registry,
+		opts...,
+	)
+	if err != nil {
+		return &SingleResult{err: replaceTopologyErr(err)}
+	}
+
+	return &SingleResult{rdr: res.Value, reg: coll.registry}
+}
+
+// Watch returns a change stream cursor used to receive notifications of changes to the collection.
+//
+// This method is preferred to running a raw aggregation with a $changeStream stage because it
+// supports resumability in the case of some errors. The collection must have read concern majority or no read concern
+// for a change stream to be created successfully.
+func (coll *Collection) Watch(ctx context.Context, pipeline interface{},
+	opts ...*options.ChangeStreamOptions) (*ChangeStream, error) {
+	return newChangeStream(ctx, coll, pipeline, opts...)
+}
+
+// Indexes returns the index view for this collection.
+func (coll *Collection) Indexes() IndexView {
+	return IndexView{coll: coll}
+}
+
+// Drop drops this collection from database.
+func (coll *Collection) Drop(ctx context.Context) error {
+	if ctx == nil {
+		ctx = context.Background()
+	}
+
+	sess := sessionFromContext(ctx)
+
+	err := coll.client.ValidSession(sess)
+	if err != nil {
+		return err
+	}
+
+	wc := coll.writeConcern
+	if sess != nil && sess.TransactionRunning() {
+		wc = nil
+	}
+
+	cmd := command.DropCollection{
+		DB:           coll.db.name,
+		Collection:   coll.name,
+		WriteConcern: wc,
+		Session:      sess,
+		Clock:        coll.client.clock,
+	}
+	_, err = driver.DropCollection(
+		ctx, cmd,
+		coll.client.topology,
+		coll.writeSelector,
+		coll.client.id,
+		coll.client.topology.SessionPool,
+	)
+	if err != nil && !command.IsNotFound(err) {
+		return replaceTopologyErr(err)
+	}
+	return nil
+}
diff --git a/vendor/github.com/mongodb/mongo-go-driver/mongo/cursor.go b/vendor/github.com/mongodb/mongo-go-driver/mongo/cursor.go
new file mode 100644
index 0000000..a9dc13d
--- /dev/null
+++ b/vendor/github.com/mongodb/mongo-go-driver/mongo/cursor.go
@@ -0,0 +1,137 @@
+// Copyright (C) MongoDB, Inc. 2017-present.
+//
+// Licensed under the Apache License, Version 2.0 (the "License"); you may
+// not use this file except in compliance with the License. You may obtain
+// a copy of the License at http://www.apache.org/licenses/LICENSE-2.0
+
+package mongo
+
+import (
+	"context"
+	"errors"
+
+	"github.com/mongodb/mongo-go-driver/bson"
+	"github.com/mongodb/mongo-go-driver/bson/bsoncodec"
+	"github.com/mongodb/mongo-go-driver/x/mongo/driver"
+)
+
+// Cursor is used to iterate a stream of documents. Each document is decoded into the result
+// according to the rules of the bson package.
+//
+// A typical usage of the Cursor type would be:
+//
+//		var cur *Cursor
+//		ctx := context.Background()
+//		defer cur.Close(ctx)
+//
+// 		for cur.Next(ctx) {
+//			elem := &bson.D{}
+//			if err := cur.Decode(elem); err != nil {
+// 				log.Fatal(err)
+// 			}
+//
+// 			// do something with elem....
+//		}
+//
+// 		if err := cur.Err(); err != nil {
+//			log.Fatal(err)
+//		}
+//
+type Cursor struct {
+	// Current is the BSON bytes of the current document. This property is only valid until the next
+	// call to Next or Close. If continued access is required to the bson.Raw, you must make a copy
+	// of it.
+	Current bson.Raw
+
+	bc       batchCursor
+	pos      int
+	batch    []byte
+	registry *bsoncodec.Registry
+
+	err error
+}
+
+func newCursor(bc batchCursor, registry *bsoncodec.Registry) (*Cursor, error) {
+	if registry == nil {
+		registry = bson.DefaultRegistry
+	}
+	if bc == nil {
+		return nil, errors.New("batch cursor must not be nil")
+	}
+	return &Cursor{bc: bc, pos: 0, batch: make([]byte, 0, 256), registry: registry}, nil
+}
+
+func newEmptyCursor() *Cursor {
+	return &Cursor{bc: driver.NewEmptyBatchCursor()}
+}
+
+// ID returns the ID of this cursor.
+func (c *Cursor) ID() int64 { return c.bc.ID() }
+
+func (c *Cursor) advanceCurrentDocument() bool {
+	if len(c.batch[c.pos:]) < 4 {
+		c.err = errors.New("could not read next document: insufficient bytes")
+		return false
+	}
+	length := (int(c.batch[c.pos]) | int(c.batch[c.pos+1])<<8 | int(c.batch[c.pos+2])<<16 | int(c.batch[c.pos+3])<<24)
+	if len(c.batch[c.pos:]) < length {
+		c.err = errors.New("could not read next document: insufficient bytes")
+		return false
+	}
+	if len(c.Current) > 4 {
+		c.Current[0], c.Current[1], c.Current[2], c.Current[3] = 0x00, 0x00, 0x00, 0x00 // Invalidate the current document
+	}
+	c.Current = c.batch[c.pos : c.pos+length]
+	c.pos += length
+	return true
+}
+
+// Next gets the next result from this cursor. Returns true if there were no errors and the next
+// result is available for decoding.
+func (c *Cursor) Next(ctx context.Context) bool {
+	if ctx == nil {
+		ctx = context.Background()
+	}
+	if c.pos < len(c.batch) {
+		return c.advanceCurrentDocument()
+	}
+
+	// clear the batch
+	c.batch = c.batch[:0]
+	c.pos = 0
+	c.Current = c.Current[:0]
+
+	// call the Next method in a loop until at least one document is returned in the next batch or
+	// the context times out.
+	for len(c.batch) == 0 {
+		// If we don't have a next batch
+		if !c.bc.Next(ctx) {
+			// Do we have an error? If so we return false.
+			c.err = c.bc.Err()
+			if c.err != nil {
+				return false
+			}
+			// Is the cursor ID zero?
+			if c.bc.ID() == 0 {
+				return false
+			}
+			// empty batch, but cursor is still valid, so continue.
+			continue
+		}
+
+		c.batch = c.bc.Batch(c.batch[:0])
+	}
+
+	return c.advanceCurrentDocument()
+}
+
+// Decode will decode the current document into val.
+func (c *Cursor) Decode(val interface{}) error {
+	return bson.UnmarshalWithRegistry(c.registry, c.Current, val)
+}
+
+// Err returns the current error.
+func (c *Cursor) Err() error { return c.err }
+
+// Close closes this cursor.
+func (c *Cursor) Close(ctx context.Context) error { return c.bc.Close(ctx) }
diff --git a/vendor/github.com/mongodb/mongo-go-driver/mongo/database.go b/vendor/github.com/mongodb/mongo-go-driver/mongo/database.go
new file mode 100644
index 0000000..9575e06
--- /dev/null
+++ b/vendor/github.com/mongodb/mongo-go-driver/mongo/database.go
@@ -0,0 +1,282 @@
+// Copyright (C) MongoDB, Inc. 2017-present.
+//
+// Licensed under the Apache License, Version 2.0 (the "License"); you may
+// not use this file except in compliance with the License. You may obtain
+// a copy of the License at http://www.apache.org/licenses/LICENSE-2.0
+
+package mongo
+
+import (
+	"context"
+
+	"github.com/mongodb/mongo-go-driver/bson/bsoncodec"
+	"github.com/mongodb/mongo-go-driver/mongo/options"
+	"github.com/mongodb/mongo-go-driver/mongo/readconcern"
+	"github.com/mongodb/mongo-go-driver/mongo/readpref"
+	"github.com/mongodb/mongo-go-driver/mongo/writeconcern"
+	"github.com/mongodb/mongo-go-driver/x/mongo/driver"
+	"github.com/mongodb/mongo-go-driver/x/network/command"
+	"github.com/mongodb/mongo-go-driver/x/network/description"
+)
+
+// Database performs operations on a given database.
+type Database struct {
+	client         *Client
+	name           string
+	readConcern    *readconcern.ReadConcern
+	writeConcern   *writeconcern.WriteConcern
+	readPreference *readpref.ReadPref
+	readSelector   description.ServerSelector
+	writeSelector  description.ServerSelector
+	registry       *bsoncodec.Registry
+}
+
+func newDatabase(client *Client, name string, opts ...*options.DatabaseOptions) *Database {
+	dbOpt := options.MergeDatabaseOptions(opts...)
+
+	rc := client.readConcern
+	if dbOpt.ReadConcern != nil {
+		rc = dbOpt.ReadConcern
+	}
+
+	rp := client.readPreference
+	if dbOpt.ReadPreference != nil {
+		rp = dbOpt.ReadPreference
+	}
+
+	wc := client.writeConcern
+	if dbOpt.WriteConcern != nil {
+		wc = dbOpt.WriteConcern
+	}
+
+	db := &Database{
+		client:         client,
+		name:           name,
+		readPreference: rp,
+		readConcern:    rc,
+		writeConcern:   wc,
+		registry:       client.registry,
+	}
+
+	db.readSelector = description.CompositeSelector([]description.ServerSelector{
+		description.ReadPrefSelector(db.readPreference),
+		description.LatencySelector(db.client.localThreshold),
+	})
+
+	db.writeSelector = description.CompositeSelector([]description.ServerSelector{
+		description.WriteSelector(),
+		description.LatencySelector(db.client.localThreshold),
+	})
+
+	return db
+}
+
+// Client returns the Client the database was created from.
+func (db *Database) Client() *Client {
+	return db.client
+}
+
+// Name returns the name of the database.
+func (db *Database) Name() string {
+	return db.name
+}
+
+// Collection gets a handle for a given collection in the database.
+func (db *Database) Collection(name string, opts ...*options.CollectionOptions) *Collection {
+	return newCollection(db, name, opts...)
+}
+
+func (db *Database) processRunCommand(ctx context.Context, cmd interface{}, opts ...*options.RunCmdOptions) (command.Read,
+	description.ServerSelector, error) {
+
+	if ctx == nil {
+		ctx = context.Background()
+	}
+
+	sess := sessionFromContext(ctx)
+	runCmd := options.MergeRunCmdOptions(opts...)
+
+	if err := db.client.ValidSession(sess); err != nil {
+		return command.Read{}, nil, err
+	}
+
+	rp := runCmd.ReadPreference
+	if rp == nil {
+		if sess != nil && sess.TransactionRunning() {
+			rp = sess.CurrentRp // override with transaction read pref if specified
+		}
+		if rp == nil {
+			rp = readpref.Primary() // set to primary if nothing specified in options
+		}
+	}
+
+	runCmdDoc, err := transformDocument(db.registry, cmd)
+	if err != nil {
+		return command.Read{}, nil, err
+	}
+
+	readSelect := description.CompositeSelector([]description.ServerSelector{
+		description.ReadPrefSelector(rp),
+		description.LatencySelector(db.client.localThreshold),
+	})
+
+	return command.Read{
+		DB:       db.Name(),
+		Command:  runCmdDoc,
+		ReadPref: rp,
+		Session:  sess,
+		Clock:    db.client.clock,
+	}, readSelect, nil
+}
+
+// RunCommand runs a command on the database. A user can supply a custom
+// context to this method, or nil to default to context.Background().
+func (db *Database) RunCommand(ctx context.Context, runCommand interface{}, opts ...*options.RunCmdOptions) *SingleResult {
+	if ctx == nil {
+		ctx = context.Background()
+	}
+
+	readCmd, readSelect, err := db.processRunCommand(ctx, runCommand, opts...)
+	if err != nil {
+		return &SingleResult{err: err}
+	}
+
+	doc, err := driver.Read(ctx,
+		readCmd,
+		db.client.topology,
+		readSelect,
+		db.client.id,
+		db.client.topology.SessionPool,
+	)
+
+	return &SingleResult{err: replaceTopologyErr(err), rdr: doc, reg: db.registry}
+}
+
+// RunCommandCursor runs a command on the database and returns a cursor over the resulting reader. A user can supply
+// a custom context to this method, or nil to default to context.Background().
+func (db *Database) RunCommandCursor(ctx context.Context, runCommand interface{}, opts ...*options.RunCmdOptions) (*Cursor, error) {
+	if ctx == nil {
+		ctx = context.Background()
+	}
+
+	readCmd, readSelect, err := db.processRunCommand(ctx, runCommand, opts...)
+	if err != nil {
+		return nil, err
+	}
+
+	batchCursor, err := driver.ReadCursor(
+		ctx,
+		readCmd,
+		db.client.topology,
+		readSelect,
+		db.client.id,
+		db.client.topology.SessionPool,
+	)
+	if err != nil {
+		return nil, replaceTopologyErr(err)
+	}
+
+	cursor, err := newCursor(batchCursor, db.registry)
+	return cursor, replaceTopologyErr(err)
+}
+
+// Drop drops this database from mongodb.
+func (db *Database) Drop(ctx context.Context) error {
+	if ctx == nil {
+		ctx = context.Background()
+	}
+
+	sess := sessionFromContext(ctx)
+
+	err := db.client.ValidSession(sess)
+	if err != nil {
+		return err
+	}
+
+	cmd := command.DropDatabase{
+		DB:      db.name,
+		Session: sess,
+		Clock:   db.client.clock,
+	}
+	_, err = driver.DropDatabase(
+		ctx, cmd,
+		db.client.topology,
+		db.writeSelector,
+		db.client.id,
+		db.client.topology.SessionPool,
+	)
+	if err != nil && !command.IsNotFound(err) {
+		return replaceTopologyErr(err)
+	}
+	return nil
+}
+
+// ListCollections list collections from mongodb database.
+func (db *Database) ListCollections(ctx context.Context, filter interface{}, opts ...*options.ListCollectionsOptions) (*Cursor, error) {
+	if ctx == nil {
+		ctx = context.Background()
+	}
+
+	sess := sessionFromContext(ctx)
+
+	err := db.client.ValidSession(sess)
+	if err != nil {
+		return nil, err
+	}
+
+	filterDoc, err := transformDocument(db.registry, filter)
+	if err != nil {
+		return nil, err
+	}
+
+	cmd := command.ListCollections{
+		DB:       db.name,
+		Filter:   filterDoc,
+		ReadPref: readpref.Primary(), // list collections must be run on a primary by default
+		Session:  sess,
+		Clock:    db.client.clock,
+	}
+
+	readSelector := description.CompositeSelector([]description.ServerSelector{
+		description.ReadPrefSelector(readpref.Primary()),
+		description.LatencySelector(db.client.localThreshold),
+	})
+	batchCursor, err := driver.ListCollections(
+		ctx, cmd,
+		db.client.topology,
+		readSelector,
+		db.client.id,
+		db.client.topology.SessionPool,
+		opts...,
+	)
+	if err != nil {
+		return nil, replaceTopologyErr(err)
+	}
+
+	cursor, err := newCursor(batchCursor, db.registry)
+	return cursor, replaceTopologyErr(err)
+}
+
+// ReadConcern returns the read concern of this database.
+func (db *Database) ReadConcern() *readconcern.ReadConcern {
+	return db.readConcern
+}
+
+// ReadPreference returns the read preference of this database.
+func (db *Database) ReadPreference() *readpref.ReadPref {
+	return db.readPreference
+}
+
+// WriteConcern returns the write concern of this database.
+func (db *Database) WriteConcern() *writeconcern.WriteConcern {
+	return db.writeConcern
+}
+
+// Watch returns a change stream cursor used to receive information of changes to the database. This method is preferred
+// to running a raw aggregation with a $changeStream stage because it supports resumability in the case of some errors.
+// The database must have read concern majority or no read concern for a change stream to be created successfully.
+func (db *Database) Watch(ctx context.Context, pipeline interface{},
+	opts ...*options.ChangeStreamOptions) (*ChangeStream, error) {
+
+	return newDbChangeStream(ctx, db, pipeline, opts...)
+}
diff --git a/vendor/github.com/mongodb/mongo-go-driver/mongo/doc.go b/vendor/github.com/mongodb/mongo-go-driver/mongo/doc.go
new file mode 100644
index 0000000..4f7f819
--- /dev/null
+++ b/vendor/github.com/mongodb/mongo-go-driver/mongo/doc.go
@@ -0,0 +1,60 @@
+// Copyright (C) MongoDB, Inc. 2017-present.
+//
+// Licensed under the Apache License, Version 2.0 (the "License"); you may
+// not use this file except in compliance with the License. You may obtain
+// a copy of the License at http://www.apache.org/licenses/LICENSE-2.0
+
+// NOTE: This documentation should be kept in line with the Example* test functions.
+
+// Package mongo provides a MongoDB Driver API for Go.
+//
+// Basic usage of the driver starts with creating a Client from a connection
+// string. To do so, call the NewClient and Connect functions:
+//
+// 		client, err := NewClient("mongodb://foo:bar@localhost:27017")
+// 		if err != nil { return err }
+// 		ctx, cancel := context.WithTimeout(context.Background(), 20*time.Second)
+// 		defer cancel()
+// 		err = client.Connect(ctx)
+// 		if err != nil { return err }
+//
+// This will create a new client and start monitoring the MongoDB server on localhost.
+// The Database and Collection types can be used to access the database:
+//
+//    collection := client.Database("baz").Collection("qux")
+//
+// A Collection can be used to query the database or insert documents:
+//
+//    res, err := collection.InsertOne(context.Background(), bson.M{"hello": "world"})
+//    if err != nil { return err }
+//    id := res.InsertedID
+//
+// Several methods return a cursor, which can be used like this:
+//
+//    cur, err := collection.Find(context.Background(), bson.D{})
+//    if err != nil { log.Fatal(err) }
+//    defer cur.Close(context.Background())
+//    for cur.Next(context.Background()) {
+//       raw, err := cur.DecodeBytes()
+//       if err != nil { log.Fatal(err) }
+//       // do something with elem....
+//    }
+//    if err := cur.Err(); err != nil {
+//    		return err
+//    }
+//
+// Methods that only return a single document will return a *SingleResult, which works
+// like a *sql.Row:
+//
+// 	  result := struct{
+// 	  	Foo string
+// 	  	Bar int32
+// 	  }{}
+//    filter := bson.D{{"hello", "world"}}
+//    err := collection.FindOne(context.Background(), filter).Decode(&result)
+//    if err != nil { return err }
+//    // do something with result...
+//
+// Additional examples can be found under the examples directory in the driver's repository and
+// on the MongoDB website.
+package mongo
diff --git a/vendor/github.com/mongodb/mongo-go-driver/mongo/errors.go b/vendor/github.com/mongodb/mongo-go-driver/mongo/errors.go
new file mode 100644
index 0000000..3505bcc
--- /dev/null
+++ b/vendor/github.com/mongodb/mongo-go-driver/mongo/errors.go
@@ -0,0 +1,186 @@
+// Copyright (C) MongoDB, Inc. 2017-present.
+//
+// Licensed under the Apache License, Version 2.0 (the "License"); you may
+// not use this file except in compliance with the License. You may obtain
+// a copy of the License at http://www.apache.org/licenses/LICENSE-2.0
+
+package mongo
+
+import (
+	"bytes"
+	"errors"
+	"fmt"
+
+	"github.com/mongodb/mongo-go-driver/bson"
+	"github.com/mongodb/mongo-go-driver/x/mongo/driver"
+	"github.com/mongodb/mongo-go-driver/x/mongo/driver/topology"
+	"github.com/mongodb/mongo-go-driver/x/network/command"
+	"github.com/mongodb/mongo-go-driver/x/network/result"
+)
+
+// ErrUnacknowledgedWrite is returned from functions that have an unacknowledged
+// write concern.
+var ErrUnacknowledgedWrite = errors.New("unacknowledged write")
+
+// ErrClientDisconnected is returned when a user attempts to call a method on a
+// disconnected client
+var ErrClientDisconnected = errors.New("client is disconnected")
+
+// ErrNilDocument is returned when a user attempts to pass a nil document or filter
+// to a function where the field is required.
+var ErrNilDocument = errors.New("document is nil")
+
+// ErrEmptySlice is returned when a user attempts to pass an empty slice as input
+// to a function wehere the field is required.
+var ErrEmptySlice = errors.New("must provide at least one element in input slice")
+
+func replaceTopologyErr(err error) error {
+	if err == topology.ErrTopologyClosed {
+		return ErrClientDisconnected
+	}
+	return err
+}
+
+// WriteError is a non-write concern failure that occurred as a result of a write
+// operation.
+type WriteError struct {
+	Index   int
+	Code    int
+	Message string
+}
+
+func (we WriteError) Error() string { return we.Message }
+
+// WriteErrors is a group of non-write concern failures that occurred as a result
+// of a write operation.
+type WriteErrors []WriteError
+
+func (we WriteErrors) Error() string {
+	var buf bytes.Buffer
+	fmt.Fprint(&buf, "write errors: [")
+	for idx, err := range we {
+		if idx != 0 {
+			fmt.Fprintf(&buf, ", ")
+		}
+		fmt.Fprintf(&buf, "{%s}", err)
+	}
+	fmt.Fprint(&buf, "]")
+	return buf.String()
+}
+
+func writeErrorsFromResult(rwes []result.WriteError) WriteErrors {
+	wes := make(WriteErrors, 0, len(rwes))
+	for _, err := range rwes {
+		wes = append(wes, WriteError{Index: err.Index, Code: err.Code, Message: err.ErrMsg})
+	}
+	return wes
+}
+
+// WriteConcernError is a write concern failure that occurred as a result of a
+// write operation.
+type WriteConcernError struct {
+	Code    int
+	Message string
+	Details bson.Raw
+}
+
+func (wce WriteConcernError) Error() string { return wce.Message }
+
+// WriteException is an error for a non-bulk write operation.
+type WriteException struct {
+	WriteConcernError *WriteConcernError
+	WriteErrors       WriteErrors
+}
+
+func (mwe WriteException) Error() string {
+	var buf bytes.Buffer
+	fmt.Fprint(&buf, "multiple write errors: [")
+	fmt.Fprintf(&buf, "{%s}, ", mwe.WriteErrors)
+	fmt.Fprintf(&buf, "{%s}]", mwe.WriteConcernError)
+	return buf.String()
+}
+
+func convertBulkWriteErrors(errors []driver.BulkWriteError) []BulkWriteError {
+	bwErrors := make([]BulkWriteError, 0, len(errors))
+	for _, err := range errors {
+		bwErrors = append(bwErrors, BulkWriteError{
+			WriteError{
+				Index:   err.Index,
+				Code:    err.Code,
+				Message: err.ErrMsg,
+			},
+			dispatchToMongoModel(err.Model),
+		})
+	}
+
+	return bwErrors
+}
+
+func convertWriteConcernError(wce *result.WriteConcernError) *WriteConcernError {
+	if wce == nil {
+		return nil
+	}
+
+	return &WriteConcernError{Code: wce.Code, Message: wce.ErrMsg, Details: wce.ErrInfo}
+}
+
+// BulkWriteError is an error for one operation in a bulk write.
+type BulkWriteError struct {
+	WriteError
+	Request WriteModel
+}
+
+func (bwe BulkWriteError) Error() string {
+	var buf bytes.Buffer
+	fmt.Fprintf(&buf, "{%s}", bwe.WriteError)
+	return buf.String()
+}
+
+// BulkWriteException is an error for a bulk write operation.
+type BulkWriteException struct {
+	WriteConcernError *WriteConcernError
+	WriteErrors       []BulkWriteError
+}
+
+func (bwe BulkWriteException) Error() string {
+	var buf bytes.Buffer
+	fmt.Fprint(&buf, "bulk write error: [")
+	fmt.Fprintf(&buf, "{%s}, ", bwe.WriteErrors)
+	fmt.Fprintf(&buf, "{%s}]", bwe.WriteConcernError)
+	return buf.String()
+}
+
+// returnResult is used to determine if a function calling processWriteError should return
+// the result or return nil. Since the processWriteError function is used by many different
+// methods, both *One and *Many, we need a way to differentiate if the method should return
+// the result and the error.
+type returnResult int
+
+const (
+	rrNone returnResult = 1 << iota // None means do not return the result ever.
+	rrOne                           // One means return the result if this was called by a *One method.
+	rrMany                          // Many means return the result is this was called by a *Many method.
+
+	rrAll returnResult = rrOne | rrMany // All means always return the result.
+)
+
+// processWriteError handles processing the result of a write operation. If the retrunResult matches
+// the calling method's type, it should return the result object in addition to the error.
+// This function will wrap the errors from other packages and return them as errors from this package.
+//
+// WriteConcernError will be returned over WriteErrors if both are present.
+func processWriteError(wce *result.WriteConcernError, wes []result.WriteError, err error) (returnResult, error) {
+	switch {
+	case err == command.ErrUnacknowledgedWrite:
+		return rrAll, ErrUnacknowledgedWrite
+	case err != nil:
+		return rrNone, replaceTopologyErr(err)
+	case wce != nil || len(wes) > 0:
+		return rrMany, WriteException{
+			WriteConcernError: convertWriteConcernError(wce),
+			WriteErrors:       writeErrorsFromResult(wes),
+		}
+	default:
+		return rrAll, nil
+	}
+}
diff --git a/vendor/github.com/mongodb/mongo-go-driver/mongo/index_options_builder.go b/vendor/github.com/mongodb/mongo-go-driver/mongo/index_options_builder.go
new file mode 100644
index 0000000..abc1514
--- /dev/null
+++ b/vendor/github.com/mongodb/mongo-go-driver/mongo/index_options_builder.go
@@ -0,0 +1,134 @@
+// Copyright (C) MongoDB, Inc. 2017-present.
+//
+// Licensed under the Apache License, Version 2.0 (the "License"); you may
+// not use this file except in compliance with the License. You may obtain
+// a copy of the License at http://www.apache.org/licenses/LICENSE-2.0
+
+package mongo
+
+import (
+	"github.com/mongodb/mongo-go-driver/bson"
+)
+
+// IndexOptionsBuilder constructs a BSON document for index options
+type IndexOptionsBuilder struct {
+	document bson.D
+}
+
+// NewIndexOptionsBuilder creates a new instance of IndexOptionsBuilder
+func NewIndexOptionsBuilder() *IndexOptionsBuilder {
+	return &IndexOptionsBuilder{}
+}
+
+// Background sets the background option
+func (iob *IndexOptionsBuilder) Background(background bool) *IndexOptionsBuilder {
+	iob.document = append(iob.document, bson.E{"background", background})
+	return iob
+}
+
+// ExpireAfterSeconds sets the expireAfterSeconds option
+func (iob *IndexOptionsBuilder) ExpireAfterSeconds(expireAfterSeconds int32) *IndexOptionsBuilder {
+	iob.document = append(iob.document, bson.E{"expireAfterSeconds", expireAfterSeconds})
+	return iob
+}
+
+// Name sets the name option
+func (iob *IndexOptionsBuilder) Name(name string) *IndexOptionsBuilder {
+	iob.document = append(iob.document, bson.E{"name", name})
+	return iob
+}
+
+// Sparse sets the sparse option
+func (iob *IndexOptionsBuilder) Sparse(sparse bool) *IndexOptionsBuilder {
+	iob.document = append(iob.document, bson.E{"sparse", sparse})
+	return iob
+}
+
+// StorageEngine sets the storageEngine option
+func (iob *IndexOptionsBuilder) StorageEngine(storageEngine interface{}) *IndexOptionsBuilder {
+	iob.document = append(iob.document, bson.E{"storageEngine", storageEngine})
+	return iob
+}
+
+// Unique sets the unique option
+func (iob *IndexOptionsBuilder) Unique(unique bool) *IndexOptionsBuilder {
+	iob.document = append(iob.document, bson.E{"unique", unique})
+	return iob
+}
+
+// Version sets the version option
+func (iob *IndexOptionsBuilder) Version(version int32) *IndexOptionsBuilder {
+	iob.document = append(iob.document, bson.E{"v", version})
+	return iob
+}
+
+// DefaultLanguage sets the defaultLanguage option
+func (iob *IndexOptionsBuilder) DefaultLanguage(defaultLanguage string) *IndexOptionsBuilder {
+	iob.document = append(iob.document, bson.E{"default_language", defaultLanguage})
+	return iob
+}
+
+// LanguageOverride sets the languageOverride option
+func (iob *IndexOptionsBuilder) LanguageOverride(languageOverride string) *IndexOptionsBuilder {
+	iob.document = append(iob.document, bson.E{"language_override", languageOverride})
+	return iob
+}
+
+// TextVersion sets the textVersion option
+func (iob *IndexOptionsBuilder) TextVersion(textVersion int32) *IndexOptionsBuilder {
+	iob.document = append(iob.document, bson.E{"textIndexVersion", textVersion})
+	return iob
+}
+
+// Weights sets the weights option
+func (iob *IndexOptionsBuilder) Weights(weights interface{}) *IndexOptionsBuilder {
+	iob.document = append(iob.document, bson.E{"weights", weights})
+	return iob
+}
+
+// SphereVersion sets the sphereVersion option
+func (iob *IndexOptionsBuilder) SphereVersion(sphereVersion int32) *IndexOptionsBuilder {
+	iob.document = append(iob.document, bson.E{"2dsphereIndexVersion", sphereVersion})
+	return iob
+}
+
+// Bits sets the bits option
+func (iob *IndexOptionsBuilder) Bits(bits int32) *IndexOptionsBuilder {
+	iob.document = append(iob.document, bson.E{"bits", bits})
+	return iob
+}
+
+// Max sets the max option
+func (iob *IndexOptionsBuilder) Max(max float64) *IndexOptionsBuilder {
+	iob.document = append(iob.document, bson.E{"max", max})
+	return iob
+}
+
+// Min sets the min option
+func (iob *IndexOptionsBuilder) Min(min float64) *IndexOptionsBuilder {
+	iob.document = append(iob.document, bson.E{"min", min})
+	return iob
+}
+
+// BucketSize sets the bucketSize option
+func (iob *IndexOptionsBuilder) BucketSize(bucketSize int32) *IndexOptionsBuilder {
+	iob.document = append(iob.document, bson.E{"bucketSize", bucketSize})
+	return iob
+}
+
+// PartialFilterExpression sets the partialFilterExpression option
+func (iob *IndexOptionsBuilder) PartialFilterExpression(partialFilterExpression interface{}) *IndexOptionsBuilder {
+	iob.document = append(iob.document, bson.E{"partialFilterExpression", partialFilterExpression})
+	return iob
+}
+
+// Collation sets the collation option
+func (iob *IndexOptionsBuilder) Collation(collation interface{}) *IndexOptionsBuilder {
+	iob.document = append(iob.document, bson.E{"collation", collation})
+	return iob
+}
+
+// Build returns the BSON document from the builder
+func (iob *IndexOptionsBuilder) Build() bson.D {
+	return iob.document
+}
diff --git a/vendor/github.com/mongodb/mongo-go-driver/mongo/index_view.go b/vendor/github.com/mongodb/mongo-go-driver/mongo/index_view.go
new file mode 100644
index 0000000..1ff8d49
--- /dev/null
+++ b/vendor/github.com/mongodb/mongo-go-driver/mongo/index_view.go
@@ -0,0 +1,343 @@
+// Copyright (C) MongoDB, Inc. 2017-present.
+//
+// Licensed under the Apache License, Version 2.0 (the "License"); you may
+// not use this file except in compliance with the License. You may obtain
+// a copy of the License at http://www.apache.org/licenses/LICENSE-2.0
+
+package mongo
+
+import (
+	"bytes"
+	"context"
+	"errors"
+	"fmt"
+
+	"github.com/mongodb/mongo-go-driver/bson"
+	"github.com/mongodb/mongo-go-driver/bson/bsoncodec"
+	"github.com/mongodb/mongo-go-driver/bson/bsontype"
+	"github.com/mongodb/mongo-go-driver/mongo/options"
+	"github.com/mongodb/mongo-go-driver/mongo/readpref"
+	"github.com/mongodb/mongo-go-driver/x/bsonx"
+	"github.com/mongodb/mongo-go-driver/x/mongo/driver"
+	"github.com/mongodb/mongo-go-driver/x/network/command"
+	"github.com/mongodb/mongo-go-driver/x/network/description"
+)
+
+// ErrInvalidIndexValue indicates that the index Keys document has a value that isn't either a number or a string.
+var ErrInvalidIndexValue = errors.New("invalid index value")
+
+// ErrNonStringIndexName indicates that the index name specified in the options is not a string.
+var ErrNonStringIndexName = errors.New("index name must be a string")
+
+// ErrMultipleIndexDrop indicates that multiple indexes would be dropped from a call to IndexView.DropOne.
+var ErrMultipleIndexDrop = errors.New("multiple indexes would be dropped")
+
+// IndexView is used to create, drop, and list indexes on a given collection.
+type IndexView struct {
+	coll *Collection
+}
+
+// IndexModel contains information about an index.
+type IndexModel struct {
+	Keys    interface{}
+	Options *options.IndexOptions
+}
+
+// List returns a cursor iterating over all the indexes in the collection.
+func (iv IndexView) List(ctx context.Context, opts ...*options.ListIndexesOptions) (*Cursor, error) {
+	sess := sessionFromContext(ctx)
+
+	err := iv.coll.client.ValidSession(sess)
+	if err != nil {
+		return nil, err
+	}
+
+	listCmd := command.ListIndexes{
+		NS:      iv.coll.namespace(),
+		Session: sess,
+		Clock:   iv.coll.client.clock,
+	}
+
+	readSelector := description.CompositeSelector([]description.ServerSelector{
+		description.ReadPrefSelector(readpref.Primary()),
+		description.LatencySelector(iv.coll.client.localThreshold),
+	})
+	batchCursor, err := driver.ListIndexes(
+		ctx, listCmd,
+		iv.coll.client.topology,
+		readSelector,
+		iv.coll.client.id,
+		iv.coll.client.topology.SessionPool,
+		opts...,
+	)
+	if err != nil {
+		if err == command.ErrEmptyCursor {
+			return newEmptyCursor(), nil
+		}
+		return nil, replaceTopologyErr(err)
+	}
+
+	cursor, err := newCursor(batchCursor, iv.coll.registry)
+	return cursor, replaceTopologyErr(err)
+}
+
+// CreateOne creates a single index in the collection specified by the model.
+func (iv IndexView) CreateOne(ctx context.Context, model IndexModel, opts ...*options.CreateIndexesOptions) (string, error) {
+	names, err := iv.CreateMany(ctx, []IndexModel{model}, opts...)
+	if err != nil {
+		return "", err
+	}
+
+	return names[0], nil
+}
+
+// CreateMany creates multiple indexes in the collection specified by the models. The names of the
+// creates indexes are returned.
+func (iv IndexView) CreateMany(ctx context.Context, models []IndexModel, opts ...*options.CreateIndexesOptions) ([]string, error) {
+	names := make([]string, 0, len(models))
+	indexes := bsonx.Arr{}
+
+	for _, model := range models {
+		if model.Keys == nil {
+			return nil, fmt.Errorf("index model keys cannot be nil")
+		}
+
+		name, err := getOrGenerateIndexName(iv.coll.registry, model)
+		if err != nil {
+			return nil, err
+		}
+
+		names = append(names, name)
+
+		keys, err := transformDocument(iv.coll.registry, model.Keys)
+		if err != nil {
+			return nil, err
+		}
+		index := bsonx.Doc{{"key", bsonx.Document(keys)}}
+		if model.Options != nil {
+			optsDoc, err := iv.createOptionsDoc(model.Options)
+			if err != nil {
+				return nil, err
+			}
+
+			index = append(index, optsDoc...)
+		}
+		index = index.Set("name", bsonx.String(name))
+
+		indexes = append(indexes, bsonx.Document(index))
+	}
+
+	sess := sessionFromContext(ctx)
+
+	err := iv.coll.client.ValidSession(sess)
+	if err != nil {
+		return nil, err
+	}
+
+	cmd := command.CreateIndexes{
+		NS:      iv.coll.namespace(),
+		Indexes: indexes,
+		Session: sess,
+		Clock:   iv.coll.client.clock,
+	}
+
+	_, err = driver.CreateIndexes(
+		ctx, cmd,
+		iv.coll.client.topology,
+		iv.coll.writeSelector,
+		iv.coll.client.id,
+		iv.coll.client.topology.SessionPool,
+		opts...,
+	)
+	if err != nil {
+		return nil, err
+	}
+
+	return names, nil
+}
+
+func (iv IndexView) createOptionsDoc(opts *options.IndexOptions) (bsonx.Doc, error) {
+	optsDoc := bsonx.Doc{}
+	if opts.Background != nil {
+		optsDoc = append(optsDoc, bsonx.Elem{"background", bsonx.Boolean(*opts.Background)})
+	}
+	if opts.ExpireAfterSeconds != nil {
+		optsDoc = append(optsDoc, bsonx.Elem{"expireAfterSeconds", bsonx.Int32(*opts.ExpireAfterSeconds)})
+	}
+	if opts.Name != nil {
+		optsDoc = append(optsDoc, bsonx.Elem{"name", bsonx.String(*opts.Name)})
+	}
+	if opts.Sparse != nil {
+		optsDoc = append(optsDoc, bsonx.Elem{"sparse", bsonx.Boolean(*opts.Sparse)})
+	}
+	if opts.StorageEngine != nil {
+		doc, err := transformDocument(iv.coll.registry, opts.StorageEngine)
+		if err != nil {
+			return nil, err
+		}
+
+		optsDoc = append(optsDoc, bsonx.Elem{"storageEngine", bsonx.Document(doc)})
+	}
+	if opts.Unique != nil {
+		optsDoc = append(optsDoc, bsonx.Elem{"unique", bsonx.Boolean(*opts.Unique)})
+	}
+	if opts.Version != nil {
+		optsDoc = append(optsDoc, bsonx.Elem{"v", bsonx.Int32(*opts.Version)})
+	}
+	if opts.DefaultLanguage != nil {
+		optsDoc = append(optsDoc, bsonx.Elem{"default_language", bsonx.String(*opts.DefaultLanguage)})
+	}
+	if opts.LanguageOverride != nil {
+		optsDoc = append(optsDoc, bsonx.Elem{"language_override", bsonx.String(*opts.LanguageOverride)})
+	}
+	if opts.TextVersion != nil {
+		optsDoc = append(optsDoc, bsonx.Elem{"textIndexVersion", bsonx.Int32(*opts.TextVersion)})
+	}
+	if opts.Weights != nil {
+		weightsDoc, err := transformDocument(iv.coll.registry, opts.Weights)
+		if err != nil {
+			return nil, err
+		}
+
+		optsDoc = append(optsDoc, bsonx.Elem{"weights", bsonx.Document(weightsDoc)})
+	}
+	if opts.SphereVersion != nil {
+		optsDoc = append(optsDoc, bsonx.Elem{"2dsphereIndexVersion", bsonx.Int32(*opts.SphereVersion)})
+	}
+	if opts.Bits != nil {
+		optsDoc = append(optsDoc, bsonx.Elem{"bits", bsonx.Int32(*opts.Bits)})
+	}
+	if opts.Max != nil {
+		optsDoc = append(optsDoc, bsonx.Elem{"max", bsonx.Double(*opts.Max)})
+	}
+	if opts.Min != nil {
+		optsDoc = append(optsDoc, bsonx.Elem{"min", bsonx.Double(*opts.Min)})
+	}
+	if opts.BucketSize != nil {
+		optsDoc = append(optsDoc, bsonx.Elem{"bucketSize", bsonx.Int32(*opts.BucketSize)})
+	}
+	if opts.PartialFilterExpression != nil {
+		doc, err := transformDocument(iv.coll.registry, opts.PartialFilterExpression)
+		if err != nil {
+			return nil, err
+		}
+
+		optsDoc = append(optsDoc, bsonx.Elem{"partialFilterExpression", bsonx.Document(doc)})
+	}
+	if opts.Collation != nil {
+		doc := opts.Collation.ToDocument()
+		optsDoc = append(optsDoc, bsonx.Elem{"collation", bsonx.Document(doc)})
+	}
+
+	return optsDoc, nil
+}
+
+// DropOne drops the index with the given name from the collection.
+func (iv IndexView) DropOne(ctx context.Context, name string, opts ...*options.DropIndexesOptions) (bson.Raw, error) {
+	if name == "*" {
+		return nil, ErrMultipleIndexDrop
+	}
+
+	sess := sessionFromContext(ctx)
+
+	err := iv.coll.client.ValidSession(sess)
+	if err != nil {
+		return nil, err
+	}
+
+	cmd := command.DropIndexes{
+		NS:      iv.coll.namespace(),
+		Index:   name,
+		Session: sess,
+		Clock:   iv.coll.client.clock,
+	}
+
+	return driver.DropIndexes(
+		ctx, cmd,
+		iv.coll.client.topology,
+		iv.coll.writeSelector,
+		iv.coll.client.id,
+		iv.coll.client.topology.SessionPool,
+		opts...,
+	)
+}
+
+// DropAll drops all indexes in the collection.
+func (iv IndexView) DropAll(ctx context.Context, opts ...*options.DropIndexesOptions) (bson.Raw, error) {
+	sess := sessionFromContext(ctx)
+
+	err := iv.coll.client.ValidSession(sess)
+	if err != nil {
+		return nil, err
+	}
+
+	cmd := command.DropIndexes{
+		NS:      iv.coll.namespace(),
+		Index:   "*",
+		Session: sess,
+		Clock:   iv.coll.client.clock,
+	}
+
+	return driver.DropIndexes(
+		ctx, cmd,
+		iv.coll.client.topology,
+		iv.coll.writeSelector,
+		iv.coll.client.id,
+		iv.coll.client.topology.SessionPool,
+		opts...,
+	)
+}
+
+func getOrGenerateIndexName(registry *bsoncodec.Registry, model IndexModel) (string, error) {
+	if model.Options != nil && model.Options.Name != nil {
+		return *model.Options.Name, nil
+	}
+
+	name := bytes.NewBufferString("")
+	first := true
+
+	keys, err := transformDocument(registry, model.Keys)
+	if err != nil {
+		return "", err
+	}
+	for _, elem := range keys {
+		if !first {
+			_, err := name.WriteRune('_')
+			if err != nil {
+				return "", err
+			}
+		}
+
+		_, err := name.WriteString(elem.Key)
+		if err != nil {
+			return "", err
+		}
+
+		_, err = name.WriteRune('_')
+		if err != nil {
+			return "", err
+		}
+
+		var value string
+
+		switch elem.Value.Type() {
+		case bsontype.Int32:
+			value = fmt.Sprintf("%d", elem.Value.Int32())
+		case bsontype.Int64:
+			value = fmt.Sprintf("%d", elem.Value.Int64())
+		case bsontype.String:
+			value = elem.Value.StringValue()
+		default:
+			return "", ErrInvalidIndexValue
+		}
+
+		_, err = name.WriteString(value)
+		if err != nil {
+			return "", err
+		}
+
+		first = false
+	}
+
+	return name.String(), nil
+}
diff --git a/vendor/github.com/mongodb/mongo-go-driver/mongo/mongo.go b/vendor/github.com/mongodb/mongo-go-driver/mongo/mongo.go
new file mode 100644
index 0000000..9757d9b
--- /dev/null
+++ b/vendor/github.com/mongodb/mongo-go-driver/mongo/mongo.go
@@ -0,0 +1,242 @@
+// Copyright (C) MongoDB, Inc. 2017-present.
+//
+// Licensed under the Apache License, Version 2.0 (the "License"); you may
+// not use this file except in compliance with the License. You may obtain
+// a copy of the License at http://www.apache.org/licenses/LICENSE-2.0
+
+package mongo
+
+import (
+	"context"
+	"errors"
+	"fmt"
+	"net"
+	"reflect"
+	"strings"
+
+	"github.com/mongodb/mongo-go-driver/mongo/options"
+	"github.com/mongodb/mongo-go-driver/x/bsonx"
+
+	"github.com/mongodb/mongo-go-driver/bson"
+	"github.com/mongodb/mongo-go-driver/bson/bsoncodec"
+	"github.com/mongodb/mongo-go-driver/bson/bsontype"
+	"github.com/mongodb/mongo-go-driver/bson/primitive"
+)
+
+// Dialer is used to make network connections.
+type Dialer interface {
+	DialContext(ctx context.Context, network, address string) (net.Conn, error)
+}
+
+// BSONAppender is an interface implemented by types that can marshal a
+// provided type into BSON bytes and append those bytes to the provided []byte.
+// The AppendBSON can return a non-nil error and non-nil []byte. The AppendBSON
+// method may also write incomplete BSON to the []byte.
+type BSONAppender interface {
+	AppendBSON([]byte, interface{}) ([]byte, error)
+}
+
+// BSONAppenderFunc is an adapter function that allows any function that
+// satisfies the AppendBSON method signature to be used where a BSONAppender is
+// used.
+type BSONAppenderFunc func([]byte, interface{}) ([]byte, error)
+
+// AppendBSON implements the BSONAppender interface
+func (baf BSONAppenderFunc) AppendBSON(dst []byte, val interface{}) ([]byte, error) {
+	return baf(dst, val)
+}
+
+// MarshalError is returned when attempting to transform a value into a document
+// results in an error.
+type MarshalError struct {
+	Value interface{}
+	Err   error
+}
+
+// Error implements the error interface.
+func (me MarshalError) Error() string {
+	return fmt.Sprintf("cannot transform type %s to a *bsonx.Document", reflect.TypeOf(me.Value))
+}
+
+// Pipeline is a type that makes creating aggregation pipelines easier. It is a
+// helper and is intended for serializing to BSON.
+//
+// Example usage:
+//
+//		mongo.Pipeline{
+//			{{"$group", bson.D{{"_id", "$state"}, {"totalPop", bson.D{{"$sum", "$pop"}}}}}},
+//			{{"$match", bson.D{{"totalPop", bson.D{{"$gte", 10*1000*1000}}}}}},
+//		}
+//
+type Pipeline []bson.D
+
+// transformAndEnsureID is a hack that makes it easy to get a RawValue as the _id value. This will
+// be removed when we switch from using bsonx to bsoncore for the driver package.
+func transformAndEnsureID(registry *bsoncodec.Registry, val interface{}) (bsonx.Doc, interface{}, error) {
+	// TODO: performance is going to be pretty bad for bsonx.Doc here since we turn it into a []byte
+	// only to turn it back into a bsonx.Doc. We can fix this post beta1 when we refactor the driver
+	// package to use bsoncore.Document instead of bsonx.Doc.
+	if registry == nil {
+		registry = bson.NewRegistryBuilder().Build()
+	}
+	switch tt := val.(type) {
+	case nil:
+		return nil, nil, ErrNilDocument
+	case bsonx.Doc:
+		val = tt.Copy()
+	case []byte:
+		// Slight optimization so we'll just use MarshalBSON and not go through the codec machinery.
+		val = bson.Raw(tt)
+	}
+
+	// TODO(skriptble): Use a pool of these instead.
+	buf := make([]byte, 0, 256)
+	b, err := bson.MarshalAppendWithRegistry(registry, buf, val)
+	if err != nil {
+		return nil, nil, MarshalError{Value: val, Err: err}
+	}
+
+	d, err := bsonx.ReadDoc(b)
+	if err != nil {
+		return nil, nil, err
+	}
+
+	var id interface{}
+
+	idx := d.IndexOf("_id")
+	var idElem bsonx.Elem
+	switch idx {
+	case -1:
+		idElem = bsonx.Elem{"_id", bsonx.ObjectID(primitive.NewObjectID())}
+		d = append(d, bsonx.Elem{})
+		copy(d[1:], d)
+		d[0] = idElem
+	default:
+		idElem = d[idx]
+		copy(d[1:idx+1], d[0:idx])
+		d[0] = idElem
+	}
+
+	t, data, err := idElem.Value.MarshalAppendBSONValue(buf[:0])
+	if err != nil {
+		return nil, nil, err
+	}
+
+	err = bson.RawValue{Type: t, Value: data}.UnmarshalWithRegistry(registry, &id)
+	if err != nil {
+		return nil, nil, err
+	}
+
+	return d, id, nil
+}
+
+func transformDocument(registry *bsoncodec.Registry, val interface{}) (bsonx.Doc, error) {
+	if registry == nil {
+		registry = bson.NewRegistryBuilder().Build()
+	}
+	if val == nil {
+		return nil, ErrNilDocument
+	}
+	if doc, ok := val.(bsonx.Doc); ok {
+		return doc.Copy(), nil
+	}
+	if bs, ok := val.([]byte); ok {
+		// Slight optimization so we'll just use MarshalBSON and not go through the codec machinery.
+		val = bson.Raw(bs)
+	}
+
+	// TODO(skriptble): Use a pool of these instead.
+	buf := make([]byte, 0, 256)
+	b, err := bson.MarshalAppendWithRegistry(registry, buf[:0], val)
+	if err != nil {
+		return nil, MarshalError{Value: val, Err: err}
+	}
+	return bsonx.ReadDoc(b)
+}
+
+func ensureID(d bsonx.Doc) (bsonx.Doc, interface{}) {
+	var id interface{}
+
+	elem, err := d.LookupElementErr("_id")
+	switch err.(type) {
+	case nil:
+		id = elem
+	default:
+		oid := primitive.NewObjectID()
+		d = append(d, bsonx.Elem{"_id", bsonx.ObjectID(oid)})
+		id = oid
+	}
+	return d, id
+}
+
+func ensureDollarKey(doc bsonx.Doc) error {
+	if len(doc) == 0 {
+		return errors.New("update document must have at least one element")
+	}
+	if !strings.HasPrefix(doc[0].Key, "$") {
+		return errors.New("update document must contain key beginning with '$'")
+	}
+	return nil
+}
+
+func transformAggregatePipeline(registry *bsoncodec.Registry, pipeline interface{}) (bsonx.Arr, error) {
+	pipelineArr := bsonx.Arr{}
+	switch t := pipeline.(type) {
+	case bsoncodec.ValueMarshaler:
+		btype, val, err := t.MarshalBSONValue()
+		if err != nil {
+			return nil, err
+		}
+		if btype != bsontype.Array {
+			return nil, fmt.Errorf("ValueMarshaler returned a %v, but was expecting %v", btype, bsontype.Array)
+		}
+		err = pipelineArr.UnmarshalBSONValue(btype, val)
+		if err != nil {
+			return nil, err
+		}
+	default:
+		val := reflect.ValueOf(t)
+		if !val.IsValid() || (val.Kind() != reflect.Slice && val.Kind() != reflect.Array) {
+			return nil, fmt.Errorf("can only transform slices and arrays into aggregation pipelines, but got %v", val.Kind())
+		}
+		for idx := 0; idx < val.Len(); idx++ {
+			elem, err := transformDocument(registry, val.Index(idx).Interface())
+			if err != nil {
+				return nil, err
+			}
+			pipelineArr = append(pipelineArr, bsonx.Document(elem))
+		}
+	}
+
+	return pipelineArr, nil
+}
+
+// Build the aggregation pipeline for the CountDocument command.
+func countDocumentsAggregatePipeline(registry *bsoncodec.Registry, filter interface{}, opts *options.CountOptions) (bsonx.Arr, error) {
+	pipeline := bsonx.Arr{}
+	filterDoc, err := transformDocument(registry, filter)
+
+	if err != nil {
+		return nil, err
+	}
+	pipeline = append(pipeline, bsonx.Document(bsonx.Doc{{"$match", bsonx.Document(filterDoc)}}))
+
+	if opts != nil {
+		if opts.Skip != nil {
+			pipeline = append(pipeline, bsonx.Document(bsonx.Doc{{"$skip", bsonx.Int64(*opts.Skip)}}))
+		}
+		if opts.Limit != nil {
+			pipeline = append(pipeline, bsonx.Document(bsonx.Doc{{"$limit", bsonx.Int64(*opts.Limit)}}))
+		}
+	}
+
+	pipeline = append(pipeline, bsonx.Document(bsonx.Doc{
+		{"$group", bsonx.Document(bsonx.Doc{
+			{"_id", bsonx.Null()},
+			{"n", bsonx.Document(bsonx.Doc{{"$sum", bsonx.Int32(1)}})},
+		})},
+	},
+	))
+
+	return pipeline, nil
+}
diff --git a/vendor/github.com/mongodb/mongo-go-driver/mongo/options/aggregateoptions.go b/vendor/github.com/mongodb/mongo-go-driver/mongo/options/aggregateoptions.go
new file mode 100644
index 0000000..3700d84
--- /dev/null
+++ b/vendor/github.com/mongodb/mongo-go-driver/mongo/options/aggregateoptions.go
@@ -0,0 +1,119 @@
+// Copyright (C) MongoDB, Inc. 2017-present.
+//
+// Licensed under the Apache License, Version 2.0 (the "License"); you may
+// not use this file except in compliance with the License. You may obtain
+// a copy of the License at http://www.apache.org/licenses/LICENSE-2.0
+
+package options
+
+import "time"
+
+// AggregateOptions represents all possible options to the aggregate() function
+type AggregateOptions struct {
+	AllowDiskUse             *bool          // Enables writing to temporary files. When set to true, aggregation stages can write data to the _tmp subdirectory in the dbPath directory
+	BatchSize                *int32         // The number of documents to return per batch
+	BypassDocumentValidation *bool          // If true, allows the write to opt-out of document level validation. This only applies when the $out stage is specified
+	Collation                *Collation     // Specifies a collation
+	MaxTime                  *time.Duration // The maximum amount of time to allow the query to run
+	MaxAwaitTime             *time.Duration // The maximum amount of time for the server to wait on new documents to satisfy a tailable cursor query
+	Comment                  *string        // Enables users to specify an arbitrary string to help trace the operation through the database profiler, currentOp and logs.
+	Hint                     interface{}    // The index to use for the aggregation. The hint does not apply to $lookup and $graphLookup stages
+}
+
+// Aggregate returns a pointer to a new AggregateOptions
+func Aggregate() *AggregateOptions {
+	return &AggregateOptions{}
+}
+
+// SetAllowDiskUse enables writing to temporary files. When set to true,
+// aggregation stages can write data to the _tmp subdirectory in the
+// dbPath directory
+func (ao *AggregateOptions) SetAllowDiskUse(b bool) *AggregateOptions {
+	ao.AllowDiskUse = &b
+	return ao
+}
+
+// SetBatchSize specifies the number of documents to return per batch
+func (ao *AggregateOptions) SetBatchSize(i int32) *AggregateOptions {
+	ao.BatchSize = &i
+	return ao
+}
+
+// SetBypassDocumentValidation allows the write to opt-out of document level
+// validation. This only applies when the $out stage is specified
+// Valid for server versions >= 3.2. For servers < 3.2, this option is ignored.
+func (ao *AggregateOptions) SetBypassDocumentValidation(b bool) *AggregateOptions {
+	ao.BypassDocumentValidation = &b
+	return ao
+}
+
+// SetCollation specifies a collation.
+// Valid for server versions >= 3.4
+func (ao *AggregateOptions) SetCollation(c *Collation) *AggregateOptions {
+	ao.Collation = c
+	return ao
+}
+
+// SetMaxTime specifies the maximum amount of time to allow the query to run
+func (ao *AggregateOptions) SetMaxTime(d time.Duration) *AggregateOptions {
+	ao.MaxTime = &d
+	return ao
+}
+
+// SetMaxAwaitTime specifies the maximum amount of time for the server to
+// wait on new documents to satisfy a tailable cursor query
+// For servers < 3.2, this option is ignored
+func (ao *AggregateOptions) SetMaxAwaitTime(d time.Duration) *AggregateOptions {
+	ao.MaxAwaitTime = &d
+	return ao
+}
+
+// SetComment enables users to specify an arbitrary string to help trace the
+// operation through the database profiler, currentOp and logs.
+func (ao *AggregateOptions) SetComment(s string) *AggregateOptions {
+	ao.Comment = &s
+	return ao
+}
+
+// SetHint specifies the index to use for the aggregation. The hint does not
+// apply to $lookup and $graphLookup stages
+func (ao *AggregateOptions) SetHint(h interface{}) *AggregateOptions {
+	ao.Hint = h
+	return ao
+}
+
+// MergeAggregateOptions combines the argued AggregateOptions into a single AggregateOptions in a last-one-wins fashion
+func MergeAggregateOptions(opts ...*AggregateOptions) *AggregateOptions {
+	aggOpts := Aggregate()
+	for _, ao := range opts {
+		if ao == nil {
+			continue
+		}
+		if ao.AllowDiskUse != nil {
+			aggOpts.AllowDiskUse = ao.AllowDiskUse
+		}
+		if ao.BatchSize != nil {
+			aggOpts.BatchSize = ao.BatchSize
+		}
+		if ao.BypassDocumentValidation != nil {
+			aggOpts.BypassDocumentValidation = ao.BypassDocumentValidation
+		}
+		if ao.Collation != nil {
+			aggOpts.Collation = ao.Collation
+		}
+		if ao.MaxTime != nil {
+			aggOpts.MaxTime = ao.MaxTime
+		}
+		if ao.MaxAwaitTime != nil {
+			aggOpts.MaxAwaitTime = ao.MaxAwaitTime
+		}
+		if ao.Comment != nil {
+			aggOpts.Comment = ao.Comment
+		}
+		if ao.Hint != nil {
+			aggOpts.Hint = ao.Hint
+		}
+	}
+
+	return aggOpts
+}
diff --git a/vendor/github.com/mongodb/mongo-go-driver/mongo/options/bulkwriteoptions.go b/vendor/github.com/mongodb/mongo-go-driver/mongo/options/bulkwriteoptions.go
new file mode 100644
index 0000000..86282fa
--- /dev/null
+++ b/vendor/github.com/mongodb/mongo-go-driver/mongo/options/bulkwriteoptions.go
@@ -0,0 +1,55 @@
+// Copyright (C) MongoDB, Inc. 2017-present.
+//
+// Licensed under the Apache License, Version 2.0 (the "License"); you may
+// not use this file except in compliance with the License. You may obtain
+// a copy of the License at http://www.apache.org/licenses/LICENSE-2.0
+
+package options
+
+// DefaultOrdered is the default order for a BulkWriteOptions struct created from BulkWrite.
+var DefaultOrdered = true
+
+// BulkWriteOptions represent all possible options for a bulkWrite operation.
+type BulkWriteOptions struct {
+	BypassDocumentValidation *bool // If true, allows the write to opt out of document-level validation.
+	Ordered                  *bool // If true, when a write fails, return without performing remaining writes. Defaults to true.
+}
+
+// BulkWrite creates a new *BulkWriteOptions
+func BulkWrite() *BulkWriteOptions {
+	return &BulkWriteOptions{
+		Ordered: &DefaultOrdered,
+	}
+}
+
+// SetOrdered configures the ordered option. If true, when a write fails, the function will return without attempting
+// remaining writes. Defaults to true.
+func (b *BulkWriteOptions) SetOrdered(ordered bool) *BulkWriteOptions {
+	b.Ordered = &ordered
+	return b
+}
+
+// SetBypassDocumentValidation specifies if the write should opt out of document-level validation.
+// Valid for server versions >= 3.2. For servers < 3.2, this option is ignored.
+func (b *BulkWriteOptions) SetBypassDocumentValidation(bypass bool) *BulkWriteOptions {
+	b.BypassDocumentValidation = &bypass
+	return b
+}
+
+// MergeBulkWriteOptions combines the given *BulkWriteOptions into a single *BulkWriteOptions in a last one wins fashion.
+func MergeBulkWriteOptions(opts ...*BulkWriteOptions) *BulkWriteOptions {
+	b := BulkWrite()
+	for _, opt := range opts {
+		if opt == nil {
+			continue
+		}
+		if opt.Ordered != nil {
+			b.Ordered = opt.Ordered
+		}
+		if opt.BypassDocumentValidation != nil {
+			b.BypassDocumentValidation = opt.BypassDocumentValidation
+		}
+	}
+
+	return b
+}
diff --git a/vendor/github.com/mongodb/mongo-go-driver/mongo/options/changestreamoptions.go b/vendor/github.com/mongodb/mongo-go-driver/mongo/options/changestreamoptions.go
new file mode 100644
index 0000000..c8776ac
--- /dev/null
+++ b/vendor/github.com/mongodb/mongo-go-driver/mongo/options/changestreamoptions.go
@@ -0,0 +1,97 @@
+// Copyright (C) MongoDB, Inc. 2017-present.
+//
+// Licensed under the Apache License, Version 2.0 (the "License"); you may
+// not use this file except in compliance with the License. You may obtain
+// a copy of the License at http://www.apache.org/licenses/LICENSE-2.0
+
+package options
+
+import (
+	"github.com/mongodb/mongo-go-driver/bson/primitive"
+	"time"
+)
+
+// ChangeStreamOptions represents all possible options to a change stream
+type ChangeStreamOptions struct {
+	BatchSize            *int32               // The number of documents to return per batch
+	Collation            *Collation           // Specifies a collation
+	FullDocument         *FullDocument        // When set to ‘updateLookup’, the change notification for partial updates will include both a delta describing the changes to the document, as well as a copy of the entire document that was changed from some time after the change occurred.
+	MaxAwaitTime         *time.Duration       // The maximum amount of time for the server to wait on new documents to satisfy a change stream query
+	ResumeAfter          interface{}          // Specifies the logical starting point for the new change stream
+	StartAtOperationTime *primitive.Timestamp // Ensures that a change stream will only provide changes that occurred after a timestamp.
+}
+
+// ChangeStream returns a pointer to a new ChangeStreamOptions
+func ChangeStream() *ChangeStreamOptions {
+	return &ChangeStreamOptions{}
+}
+
+// SetBatchSize specifies the number of documents to return per batch
+func (cso *ChangeStreamOptions) SetBatchSize(i int32) *ChangeStreamOptions {
+	cso.BatchSize = &i
+	return cso
+}
+
+// SetCollation specifies a collation
+func (cso *ChangeStreamOptions) SetCollation(c Collation) *ChangeStreamOptions {
+	cso.Collation = &c
+	return cso
+}
+
+// SetFullDocument specifies the fullDocument option.
+// When set to ‘updateLookup’, the change notification for partial updates will
+// include both a delta describing the changes to the document, as well as a
+// copy of the entire document that was changed from some time after the change
+// occurred.
+func (cso *ChangeStreamOptions) SetFullDocument(fd FullDocument) *ChangeStreamOptions {
+	cso.FullDocument = &fd
+	return cso
+}
+
+// SetMaxAwaitTime specifies the maximum amount of time for the server to wait on new documents to satisfy a change stream query
+func (cso *ChangeStreamOptions) SetMaxAwaitTime(d time.Duration) *ChangeStreamOptions {
+	cso.MaxAwaitTime = &d
+	return cso
+}
+
+// SetResumeAfter specifies the logical starting point for the new change stream
+func (cso *ChangeStreamOptions) SetResumeAfter(rt interface{}) *ChangeStreamOptions {
+	cso.ResumeAfter = rt
+	return cso
+}
+
+// SetStartAtOperationTime ensures that a change stream will only provide changes that occurred after a specified timestamp.
+func (cso *ChangeStreamOptions) SetStartAtOperationTime(t *primitive.Timestamp) *ChangeStreamOptions {
+	cso.StartAtOperationTime = t
+	return cso
+}
+
+// MergeChangeStreamOptions combines the argued ChangeStreamOptions into a single ChangeStreamOptions in a last-one-wins fashion
+func MergeChangeStreamOptions(opts ...*ChangeStreamOptions) *ChangeStreamOptions {
+	csOpts := ChangeStream()
+	for _, cso := range opts {
+		if cso == nil {
+			continue
+		}
+		if cso.BatchSize != nil {
+			csOpts.BatchSize = cso.BatchSize
+		}
+		if cso.Collation != nil {
+			csOpts.Collation = cso.Collation
+		}
+		if cso.FullDocument != nil {
+			csOpts.FullDocument = cso.FullDocument
+		}
+		if cso.MaxAwaitTime != nil {
+			csOpts.MaxAwaitTime = cso.MaxAwaitTime
+		}
+		if cso.ResumeAfter != nil {
+			csOpts.ResumeAfter = cso.ResumeAfter
+		}
+		if cso.StartAtOperationTime != nil {
+			csOpts.StartAtOperationTime = cso.StartAtOperationTime
+		}
+	}
+
+	return csOpts
+}
diff --git a/vendor/github.com/mongodb/mongo-go-driver/mongo/options/clientoptions.go b/vendor/github.com/mongodb/mongo-go-driver/mongo/options/clientoptions.go
new file mode 100644
index 0000000..e09a9c1
--- /dev/null
+++ b/vendor/github.com/mongodb/mongo-go-driver/mongo/options/clientoptions.go
@@ -0,0 +1,424 @@
+// Copyright (C) MongoDB, Inc. 2017-present.
+//
+// Licensed under the Apache License, Version 2.0 (the "License"); you may
+// not use this file except in compliance with the License. You may obtain
+// a copy of the License at http://www.apache.org/licenses/LICENSE-2.0
+
+package options
+
+import (
+	"context"
+	"net"
+	"time"
+
+	"github.com/mongodb/mongo-go-driver/bson/bsoncodec"
+	"github.com/mongodb/mongo-go-driver/event"
+	"github.com/mongodb/mongo-go-driver/mongo/readconcern"
+	"github.com/mongodb/mongo-go-driver/mongo/readpref"
+	"github.com/mongodb/mongo-go-driver/mongo/writeconcern"
+	"github.com/mongodb/mongo-go-driver/x/mongo/driver/topology"
+	"github.com/mongodb/mongo-go-driver/x/network/connection"
+	"github.com/mongodb/mongo-go-driver/x/network/connstring"
+)
+
+// ContextDialer makes new network connections
+type ContextDialer interface {
+	DialContext(ctx context.Context, network, address string) (net.Conn, error)
+}
+
+// SSLOpt holds client SSL options.
+//
+// Enabled indicates whether SSL should be enabled.
+//
+// ClientCertificateKeyFile specifies the file containing the client certificate and private key
+// used for authentication.
+//
+// ClientCertificateKeyPassword provides a callback that returns a password used for decrypting the
+// private key of a PEM file (if one is provided).
+//
+// Insecure indicates whether to skip the verification of the server certificate and hostname.
+//
+// CaFile specifies the file containing the certificate authority used for SSL connections.
+type SSLOpt struct {
+	Enabled                      bool
+	ClientCertificateKeyFile     string
+	ClientCertificateKeyPassword func() string
+	Insecure                     bool
+	CaFile                       string
+}
+
+// Credential holds auth options.
+//
+// AuthMechanism indicates the mechanism to use for authentication.
+// Supported values include "SCRAM-SHA-256", "SCRAM-SHA-1", "MONGODB-CR", "PLAIN", "GSSAPI", and "MONGODB-X509".
+//
+// AuthMechanismProperties specifies additional configuration options which may be used by certain
+// authentication mechanisms.
+//
+// AuthSource specifies the database to authenticate against.
+//
+// Username specifies the username that will be authenticated.
+//
+// Password specifies the password used for authentication.
+type Credential struct {
+	AuthMechanism           string
+	AuthMechanismProperties map[string]string
+	AuthSource              string
+	Username                string
+	Password                string
+}
+
+// ClientOptions represents all possbile options to configure a client.
+type ClientOptions struct {
+	TopologyOptions []topology.Option
+	ConnString      connstring.ConnString
+	RetryWrites     *bool
+	ReadPreference  *readpref.ReadPref
+	ReadConcern     *readconcern.ReadConcern
+	WriteConcern    *writeconcern.WriteConcern
+	Registry        *bsoncodec.Registry
+}
+
+// Client creates a new ClientOptions instance.
+func Client() *ClientOptions {
+	return &ClientOptions{
+		TopologyOptions: make([]topology.Option, 0),
+	}
+}
+
+// SetAppName specifies the client application name. This value is used by MongoDB when it logs
+// connection information and profile information, such as slow queries.
+func (c *ClientOptions) SetAppName(s string) *ClientOptions {
+	c.ConnString.AppName = s
+
+	return c
+}
+
+// SetAuth sets the authentication options.
+func (c *ClientOptions) SetAuth(auth Credential) *ClientOptions {
+	c.ConnString.AuthMechanism = auth.AuthMechanism
+	c.ConnString.AuthMechanismProperties = auth.AuthMechanismProperties
+	c.ConnString.AuthSource = auth.AuthSource
+	c.ConnString.Username = auth.Username
+	c.ConnString.Password = auth.Password
+
+	return c
+}
+
+// SetConnectTimeout specifies the timeout for an initial connection to a server.
+// If a custom Dialer is used, this method won't be set and the user is
+// responsible for setting the ConnectTimeout for connections on the dialer
+// themselves.
+func (c *ClientOptions) SetConnectTimeout(d time.Duration) *ClientOptions {
+	c.ConnString.ConnectTimeout = d
+	c.ConnString.ConnectTimeoutSet = true
+
+	return c
+}
+
+// SetDialer specifies a custom dialer used to dial new connections to a server.
+// If a custom dialer is not set, a net.Dialer with a 300 second keepalive time will be used by default.
+func (c *ClientOptions) SetDialer(d ContextDialer) *ClientOptions {
+	c.TopologyOptions = append(
+		c.TopologyOptions,
+		topology.WithServerOptions(func(opts ...topology.ServerOption) []topology.ServerOption {
+			return append(
+				opts,
+				topology.WithConnectionOptions(func(opts ...connection.Option) []connection.Option {
+					return append(
+						opts,
+						connection.WithDialer(func(connection.Dialer) connection.Dialer {
+							return d
+						}),
+					)
+				}),
+			)
+		}),
+	)
+
+	return c
+}
+
+// SetMonitor specifies a command monitor used to see commands for a client.
+func (c *ClientOptions) SetMonitor(m *event.CommandMonitor) *ClientOptions {
+	c.TopologyOptions = append(
+		c.TopologyOptions,
+		topology.WithServerOptions(func(opts ...topology.ServerOption) []topology.ServerOption {
+			return append(
+				opts,
+				topology.WithConnectionOptions(func(opts ...connection.Option) []connection.Option {
+					return append(
+						opts,
+						connection.WithMonitor(func(*event.CommandMonitor) *event.CommandMonitor {
+							return m
+						}),
+					)
+				}),
+			)
+		}),
+	)
+
+	return c
+}
+
+// SetHeartbeatInterval specifies the interval to wait between server monitoring checks.
+func (c *ClientOptions) SetHeartbeatInterval(d time.Duration) *ClientOptions {
+	c.ConnString.HeartbeatInterval = d
+	c.ConnString.HeartbeatIntervalSet = true
+
+	return c
+}
+
+// SetHosts specifies the initial list of addresses from which to discover the rest of the cluster.
+func (c *ClientOptions) SetHosts(s []string) *ClientOptions {
+	c.ConnString.Hosts = s
+
+	return c
+}
+
+// SetLocalThreshold specifies how far to distribute queries, beyond the server with the fastest
+// round-trip time. If a server's roundtrip time is more than LocalThreshold slower than the
+// the fastest, the driver will not send queries to that server.
+func (c *ClientOptions) SetLocalThreshold(d time.Duration) *ClientOptions {
+	c.ConnString.LocalThreshold = d
+	c.ConnString.LocalThresholdSet = true
+
+	return c
+}
+
+// SetMaxConnIdleTime specifies the maximum number of milliseconds that a connection can remain idle
+// in a connection pool before being removed and closed.
+func (c *ClientOptions) SetMaxConnIdleTime(d time.Duration) *ClientOptions {
+	c.ConnString.MaxConnIdleTime = d
+	c.ConnString.MaxConnIdleTimeSet = true
+
+	return c
+}
+
+// SetMaxPoolSize specifies the max size of a server's connection pool.
+func (c *ClientOptions) SetMaxPoolSize(u uint16) *ClientOptions {
+	c.ConnString.MaxPoolSize = u
+	c.ConnString.MaxPoolSizeSet = true
+
+	return c
+}
+
+// SetReadConcern specifies the read concern.
+func (c *ClientOptions) SetReadConcern(rc *readconcern.ReadConcern) *ClientOptions {
+	c.ReadConcern = rc
+
+	return c
+}
+
+// SetReadPreference specifies the read preference.
+func (c *ClientOptions) SetReadPreference(rp *readpref.ReadPref) *ClientOptions {
+	c.ReadPreference = rp
+
+	return c
+}
+
+// SetRegistry specifies the bsoncodec.Registry.
+func (c *ClientOptions) SetRegistry(registry *bsoncodec.Registry) *ClientOptions {
+	c.Registry = registry
+
+	// add registry to the server options so that it will be used for the cursors built by this client
+	c.TopologyOptions = append(
+		c.TopologyOptions,
+		topology.WithServerOptions(func(opts ...topology.ServerOption) []topology.ServerOption {
+			return append(
+				opts,
+				topology.WithRegistry(func(*bsoncodec.Registry) *bsoncodec.Registry {
+					return registry
+				}),
+			)
+		}),
+	)
+
+	return c
+}
+
+// SetReplicaSet specifies the name of the replica set of the cluster.
+func (c *ClientOptions) SetReplicaSet(s string) *ClientOptions {
+	c.ConnString.ReplicaSet = s
+
+	return c
+}
+
+// SetRetryWrites specifies whether the client has retryable writes enabled.
+func (c *ClientOptions) SetRetryWrites(b bool) *ClientOptions {
+	c.RetryWrites = &b
+
+	return c
+}
+
+// SetServerSelectionTimeout specifies a timeout in milliseconds to block for server selection.
+func (c *ClientOptions) SetServerSelectionTimeout(d time.Duration) *ClientOptions {
+	c.ConnString.ServerSelectionTimeout = d
+	c.ConnString.ServerSelectionTimeoutSet = true
+
+	return c
+}
+
+// SetSingle specifies whether the driver should connect directly to the server instead of
+// auto-discovering other servers in the cluster.
+func (c *ClientOptions) SetSingle(b bool) *ClientOptions {
+	if b {
+		c.ConnString.Connect = connstring.SingleConnect
+	} else {
+		c.ConnString.Connect = connstring.AutoConnect
+	}
+	c.ConnString.ConnectSet = true
+
+	return c
+}
+
+// SetSocketTimeout specifies the time in milliseconds to attempt to send or receive on a socket
+// before the attempt times out.
+func (c *ClientOptions) SetSocketTimeout(d time.Duration) *ClientOptions {
+	c.ConnString.SocketTimeout = d
+	c.ConnString.SocketTimeoutSet = true
+
+	return c
+}
+
+// SetSSL sets SSL options.
+func (c *ClientOptions) SetSSL(ssl *SSLOpt) *ClientOptions {
+	c.ConnString.SSL = ssl.Enabled
+	c.ConnString.SSLSet = true
+
+	if ssl.ClientCertificateKeyFile != "" {
+		c.ConnString.SSLClientCertificateKeyFile = ssl.ClientCertificateKeyFile
+		c.ConnString.SSLClientCertificateKeyFileSet = true
+	}
+
+	if ssl.ClientCertificateKeyPassword != nil {
+		c.ConnString.SSLClientCertificateKeyPassword = ssl.ClientCertificateKeyPassword
+		c.ConnString.SSLClientCertificateKeyPasswordSet = true
+	}
+
+	c.ConnString.SSLInsecure = ssl.Insecure
+	c.ConnString.SSLInsecureSet = true
+
+	if ssl.CaFile != "" {
+		c.ConnString.SSLCaFile = ssl.CaFile
+		c.ConnString.SSLCaFileSet = true
+	}
+
+	return c
+}
+
+// SetWriteConcern sets the write concern.
+func (c *ClientOptions) SetWriteConcern(wc *writeconcern.WriteConcern) *ClientOptions {
+	c.WriteConcern = wc
+
+	return c
+}
+
+// MergeClientOptions combines the given connstring and *ClientOptions into a single *ClientOptions in a last one wins
+// fashion. The given connstring will be used for the default options, which can be overwritten using the given
+// *ClientOptions.
+func MergeClientOptions(cs connstring.ConnString, opts ...*ClientOptions) *ClientOptions {
+	c := Client()
+	c.ConnString = cs
+
+	for _, opt := range opts {
+		if opt == nil {
+			continue
+		}
+		c.TopologyOptions = append(c.TopologyOptions, opt.TopologyOptions...)
+
+		if an := opt.ConnString.AppName; an != "" {
+			c.ConnString.AppName = an
+		}
+		if am := opt.ConnString.AuthMechanism; len(am) != 0 {
+			c.ConnString.AuthMechanism = am
+		}
+		if amp := opt.ConnString.AuthMechanismProperties; amp != nil {
+			c.ConnString.AuthMechanismProperties = amp
+		}
+		if as := opt.ConnString.AuthSource; len(as) != 0 {
+			c.ConnString.AuthSource = as
+		}
+		if u := opt.ConnString.Username; len(u) != 0 {
+			c.ConnString.Username = u
+		}
+		if p := opt.ConnString.Password; len(p) != 0 {
+			c.ConnString.Password = p
+		}
+		if opt.ConnString.ConnectTimeoutSet {
+			c.ConnString.ConnectTimeoutSet = true
+			c.ConnString.ConnectTimeout = opt.ConnString.ConnectTimeout
+		}
+		if opt.ConnString.HeartbeatIntervalSet {
+			c.ConnString.HeartbeatIntervalSet = true
+			c.ConnString.HeartbeatInterval = opt.ConnString.HeartbeatInterval
+		}
+		if h := opt.ConnString.Hosts; h != nil {
+			c.ConnString.Hosts = h
+		}
+		if opt.ConnString.LocalThresholdSet {
+			c.ConnString.LocalThresholdSet = true
+			c.ConnString.LocalThreshold = opt.ConnString.LocalThreshold
+		}
+		if opt.ConnString.MaxConnIdleTimeSet {
+			c.ConnString.MaxConnIdleTimeSet = true
+			c.ConnString.MaxConnIdleTime = opt.ConnString.MaxConnIdleTime
+		}
+		if opt.ConnString.MaxPoolSizeSet {
+			c.ConnString.MaxPoolSizeSet = true
+			c.ConnString.MaxPoolSize = opt.ConnString.MaxPoolSize
+		}
+		if opt.ReadConcern != nil {
+			c.ReadConcern = opt.ReadConcern
+		}
+		if opt.ReadPreference != nil {
+			c.ReadPreference = opt.ReadPreference
+		}
+		if opt.Registry != nil {
+			c.Registry = opt.Registry
+		}
+		if rs := opt.ConnString.ReplicaSet; rs != "" {
+			c.ConnString.ReplicaSet = rs
+		}
+		if opt.RetryWrites != nil {
+			c.RetryWrites = opt.RetryWrites
+		}
+		if opt.ConnString.ServerSelectionTimeoutSet {
+			c.ConnString.ServerSelectionTimeoutSet = true
+			c.ConnString.ServerSelectionTimeout = opt.ConnString.ServerSelectionTimeout
+		}
+		if opt.ConnString.ConnectSet {
+			c.ConnString.ConnectSet = true
+			c.ConnString.Connect = opt.ConnString.Connect
+		}
+		if opt.ConnString.SocketTimeoutSet {
+			c.ConnString.SocketTimeoutSet = true
+			c.ConnString.SocketTimeout = opt.ConnString.SocketTimeout
+		}
+		if opt.ConnString.SSLSet {
+			c.ConnString.SSLSet = true
+			c.ConnString.SSL = opt.ConnString.SSL
+		}
+		if opt.ConnString.SSLClientCertificateKeyFileSet {
+			c.ConnString.SSLClientCertificateKeyFileSet = true
+			c.ConnString.SSLClientCertificateKeyFile = opt.ConnString.SSLClientCertificateKeyFile
+		}
+		if opt.ConnString.SSLClientCertificateKeyPasswordSet {
+			c.ConnString.SSLClientCertificateKeyPasswordSet = true
+			c.ConnString.SSLClientCertificateKeyPassword = opt.ConnString.SSLClientCertificateKeyPassword
+		}
+		if opt.ConnString.SSLInsecureSet {
+			c.ConnString.SSLInsecureSet = true
+			c.ConnString.SSLInsecure = opt.ConnString.SSLInsecure
+		}
+		if opt.ConnString.SSLCaFileSet {
+			c.ConnString.SSLCaFileSet = true
+			c.ConnString.SSLCaFile = opt.ConnString.SSLCaFile
+		}
+		if opt.WriteConcern != nil {
+			c.WriteConcern = opt.WriteConcern
+		}
+	}
+
+	return c
+}
diff --git a/vendor/github.com/mongodb/mongo-go-driver/mongo/options/collectionoptions.go b/vendor/github.com/mongodb/mongo-go-driver/mongo/options/collectionoptions.go
new file mode 100644
index 0000000..3415505
--- /dev/null
+++ b/vendor/github.com/mongodb/mongo-go-driver/mongo/options/collectionoptions.go
@@ -0,0 +1,77 @@
+// Copyright (C) MongoDB, Inc. 2017-present.
+//
+// Licensed under the Apache License, Version 2.0 (the "License"); you may
+// not use this file except in compliance with the License. You may obtain
+// a copy of the License at http://www.apache.org/licenses/LICENSE-2.0
+
+package options
+
+import (
+	"github.com/mongodb/mongo-go-driver/bson/bsoncodec"
+	"github.com/mongodb/mongo-go-driver/mongo/readconcern"
+	"github.com/mongodb/mongo-go-driver/mongo/readpref"
+	"github.com/mongodb/mongo-go-driver/mongo/writeconcern"
+)
+
+// CollectionOptions represent all possible options to configure a Collection.
+type CollectionOptions struct {
+	ReadConcern    *readconcern.ReadConcern   // The read concern for operations in the collection.
+	WriteConcern   *writeconcern.WriteConcern // The write concern for operations in the collection.
+	ReadPreference *readpref.ReadPref         // The read preference for operations in the collection.
+	Registry       *bsoncodec.Registry        // The registry to be used to construct BSON encoders and decoders for the collection.
+}
+
+// Collection creates a new CollectionOptions instance
+func Collection() *CollectionOptions {
+	return &CollectionOptions{}
+}
+
+// SetReadConcern sets the read concern for the collection.
+func (c *CollectionOptions) SetReadConcern(rc *readconcern.ReadConcern) *CollectionOptions {
+	c.ReadConcern = rc
+	return c
+}
+
+// SetWriteConcern sets the write concern for the collection.
+func (c *CollectionOptions) SetWriteConcern(wc *writeconcern.WriteConcern) *CollectionOptions {
+	c.WriteConcern = wc
+	return c
+}
+
+// SetReadPreference sets the read preference for the collection.
+func (c *CollectionOptions) SetReadPreference(rp *readpref.ReadPref) *CollectionOptions {
+	c.ReadPreference = rp
+	return c
+}
+
+// SetRegistry sets the bsoncodec Registry for the collection.
+func (c *CollectionOptions) SetRegistry(r *bsoncodec.Registry) *CollectionOptions {
+	c.Registry = r
+	return c
+}
+
+// MergeCollectionOptions combines the *CollectionOptions arguments into a single *CollectionOptions in a last one wins
+// fashion.
+func MergeCollectionOptions(opts ...*CollectionOptions) *CollectionOptions {
+	c := Collection()
+
+	for _, opt := range opts {
+		if opt == nil {
+			continue
+		}
+		if opt.ReadConcern != nil {
+			c.ReadConcern = opt.ReadConcern
+		}
+		if opt.WriteConcern != nil {
+			c.WriteConcern = opt.WriteConcern
+		}
+		if opt.ReadPreference != nil {
+			c.ReadPreference = opt.ReadPreference
+		}
+		if opt.Registry != nil {
+			c.Registry = opt.Registry
+		}
+	}
+
+	return c
+}
diff --git a/vendor/github.com/mongodb/mongo-go-driver/mongo/options/countoptions.go b/vendor/github.com/mongodb/mongo-go-driver/mongo/options/countoptions.go
new file mode 100644
index 0000000..be3baab
--- /dev/null
+++ b/vendor/github.com/mongodb/mongo-go-driver/mongo/options/countoptions.go
@@ -0,0 +1,81 @@
+// Copyright (C) MongoDB, Inc. 2017-present.
+//
+// Licensed under the Apache License, Version 2.0 (the "License"); you may
+// not use this file except in compliance with the License. You may obtain
+// a copy of the License at http://www.apache.org/licenses/LICENSE-2.0
+
+package options
+
+import "time"
+
+// CountOptions represents all possible options to the count() function
+type CountOptions struct {
+	Collation *Collation     // Specifies a collation
+	Hint      interface{}    // The index to use
+	Limit     *int64         // The maximum number of documents to count
+	MaxTime   *time.Duration // The maximum amount of time to allow the operation to run
+	Skip      *int64         // The number of documents to skip before counting
+}
+
+// Count returns a pointer to a new CountOptions
+func Count() *CountOptions {
+	return &CountOptions{}
+}
+
+// SetCollation specifies a collation
+// Valid for server versions >= 3.4
+func (co *CountOptions) SetCollation(c *Collation) *CountOptions {
+	co.Collation = c
+	return co
+}
+
+// SetHint specifies the index to use
+func (co *CountOptions) SetHint(h interface{}) *CountOptions {
+	co.Hint = h
+	return co
+}
+
+// SetLimit specifies the maximum number of documents to count
+func (co *CountOptions) SetLimit(i int64) *CountOptions {
+	co.Limit = &i
+	return co
+}
+
+// SetMaxTime specifies the maximum amount of time to allow the operation to run
+func (co *CountOptions) SetMaxTime(d time.Duration) *CountOptions {
+	co.MaxTime = &d
+	return co
+}
+
+// SetSkip specifies the number of documents to skip before counting
+func (co *CountOptions) SetSkip(i int64) *CountOptions {
+	co.Skip = &i
+	return co
+}
+
+// MergeCountOptions combines the argued CountOptions into a single CountOptions in a last-one-wins fashion
+func MergeCountOptions(opts ...*CountOptions) *CountOptions {
+	countOpts := Count()
+	for _, co := range opts {
+		if co == nil {
+			continue
+		}
+		if co.Collation != nil {
+			countOpts.Collation = co.Collation
+		}
+		if co.Hint != nil {
+			countOpts.Hint = co.Hint
+		}
+		if co.Limit != nil {
+			countOpts.Limit = co.Limit
+		}
+		if co.MaxTime != nil {
+			countOpts.MaxTime = co.MaxTime
+		}
+		if co.Skip != nil {
+			countOpts.Skip = co.Skip
+		}
+	}
+
+	return countOpts
+}
diff --git a/vendor/github.com/mongodb/mongo-go-driver/mongo/options/dboptions.go b/vendor/github.com/mongodb/mongo-go-driver/mongo/options/dboptions.go
new file mode 100644
index 0000000..989cb13
--- /dev/null
+++ b/vendor/github.com/mongodb/mongo-go-driver/mongo/options/dboptions.go
@@ -0,0 +1,77 @@
+// Copyright (C) MongoDB, Inc. 2017-present.
+//
+// Licensed under the Apache License, Version 2.0 (the "License"); you may
+// not use this file except in compliance with the License. You may obtain
+// a copy of the License at http://www.apache.org/licenses/LICENSE-2.0
+
+package options
+
+import (
+	"github.com/mongodb/mongo-go-driver/bson/bsoncodec"
+	"github.com/mongodb/mongo-go-driver/mongo/readconcern"
+	"github.com/mongodb/mongo-go-driver/mongo/readpref"
+	"github.com/mongodb/mongo-go-driver/mongo/writeconcern"
+)
+
+// DatabaseOptions represent all possible options to configure a Database.
+type DatabaseOptions struct {
+	ReadConcern    *readconcern.ReadConcern   // The read concern for operations in the database.
+	WriteConcern   *writeconcern.WriteConcern // The write concern for operations in the database.
+	ReadPreference *readpref.ReadPref         // The read preference for operations in the database.
+	Registry       *bsoncodec.Registry        // The registry to be used to construct BSON encoders and decoders for the database.
+}
+
+// Database creates a new DatabaseOptions instance
+func Database() *DatabaseOptions {
+	return &DatabaseOptions{}
+}
+
+// SetReadConcern sets the read concern for the database.
+func (d *DatabaseOptions) SetReadConcern(rc *readconcern.ReadConcern) *DatabaseOptions {
+	d.ReadConcern = rc
+	return d
+}
+
+// SetWriteConcern sets the write concern for the database.
+func (d *DatabaseOptions) SetWriteConcern(wc *writeconcern.WriteConcern) *DatabaseOptions {
+	d.WriteConcern = wc
+	return d
+}
+
+// SetReadPreference sets the read preference for the database.
+func (d *DatabaseOptions) SetReadPreference(rp *readpref.ReadPref) *DatabaseOptions {
+	d.ReadPreference = rp
+	return d
+}
+
+// SetRegistry sets the bsoncodec Registry for the database.
+func (d *DatabaseOptions) SetRegistry(r *bsoncodec.Registry) *DatabaseOptions {
+	d.Registry = r
+	return d
+}
+
+// MergeDatabaseOptions combines the *DatabaseOptions arguments into a single *DatabaseOptions in a last one wins
+// fashion.
+func MergeDatabaseOptions(opts ...*DatabaseOptions) *DatabaseOptions {
+	d := Database()
+
+	for _, opt := range opts {
+		if opt == nil {
+			continue
+		}
+		if opt.ReadConcern != nil {
+			d.ReadConcern = opt.ReadConcern
+		}
+		if opt.WriteConcern != nil {
+			d.WriteConcern = opt.WriteConcern
+		}
+		if opt.ReadPreference != nil {
+			d.ReadPreference = opt.ReadPreference
+		}
+		if opt.Registry != nil {
+			d.Registry = opt.Registry
+		}
+	}
+
+	return d
+}
diff --git a/vendor/github.com/mongodb/mongo-go-driver/mongo/options/deleteoptions.go b/vendor/github.com/mongodb/mongo-go-driver/mongo/options/deleteoptions.go
new file mode 100644
index 0000000..919d6b8
--- /dev/null
+++ b/vendor/github.com/mongodb/mongo-go-driver/mongo/options/deleteoptions.go
@@ -0,0 +1,39 @@
+// Copyright (C) MongoDB, Inc. 2017-present.
+//
+// Licensed under the Apache License, Version 2.0 (the "License"); you may
+// not use this file except in compliance with the License. You may obtain
+// a copy of the License at http://www.apache.org/licenses/LICENSE-2.0
+
+package options
+
+// DeleteOptions represents all possible options to the deleteOne() and deleteMany() functions
+type DeleteOptions struct {
+	Collation *Collation // Specifies a collation
+}
+
+// Delete returns a pointer to a new DeleteOptions
+func Delete() *DeleteOptions {
+	return &DeleteOptions{}
+}
+
+// SetCollation specifies a collation
+// Valid for servers >= 3.4.
+func (do *DeleteOptions) SetCollation(c *Collation) *DeleteOptions {
+	do.Collation = c
+	return do
+}
+
+// MergeDeleteOptions combines the argued DeleteOptions into a single DeleteOptions in a last-one-wins fashion
+func MergeDeleteOptions(opts ...*DeleteOptions) *DeleteOptions {
+	dOpts := Delete()
+	for _, do := range opts {
+		if do == nil {
+			continue
+		}
+		if do.Collation != nil {
+			dOpts.Collation = do.Collation
+		}
+	}
+
+	return dOpts
+}
diff --git a/vendor/github.com/mongodb/mongo-go-driver/mongo/options/distinctoptions.go b/vendor/github.com/mongodb/mongo-go-driver/mongo/options/distinctoptions.go
new file mode 100644
index 0000000..3b3f588
--- /dev/null
+++ b/vendor/github.com/mongodb/mongo-go-driver/mongo/options/distinctoptions.go
@@ -0,0 +1,51 @@
+// Copyright (C) MongoDB, Inc. 2017-present.
+//
+// Licensed under the Apache License, Version 2.0 (the "License"); you may
+// not use this file except in compliance with the License. You may obtain
+// a copy of the License at http://www.apache.org/licenses/LICENSE-2.0
+
+package options
+
+import "time"
+
+// DistinctOptions represents all possible options to the distinct() function
+type DistinctOptions struct {
+	Collation *Collation     // Specifies a collation
+	MaxTime   *time.Duration // The maximum amount of time to allow the operation to run
+}
+
+// Distinct returns a pointer to a new DistinctOptions
+func Distinct() *DistinctOptions {
+	return &DistinctOptions{}
+}
+
+// SetCollation specifies a collation
+// Valid for server versions >= 3.4
+func (do *DistinctOptions) SetCollation(c *Collation) *DistinctOptions {
+	do.Collation = c
+	return do
+}
+
+// SetMaxTime specifies the maximum amount of time to allow the operation to run
+func (do *DistinctOptions) SetMaxTime(d time.Duration) *DistinctOptions {
+	do.MaxTime = &d
+	return do
+}
+
+// MergeDistinctOptions combines the argued DistinctOptions into a single DistinctOptions in a last-one-wins fashion
+func MergeDistinctOptions(opts ...*DistinctOptions) *DistinctOptions {
+	distinctOpts := Distinct()
+	for _, do := range opts {
+		if do == nil {
+			continue
+		}
+		if do.Collation != nil {
+			distinctOpts.Collation = do.Collation
+		}
+		if do.MaxTime != nil {
+			distinctOpts.MaxTime = do.MaxTime
+		}
+	}
+
+	return distinctOpts
+}
diff --git a/vendor/github.com/mongodb/mongo-go-driver/mongo/options/estimatedcountoptions.go b/vendor/github.com/mongodb/mongo-go-driver/mongo/options/estimatedcountoptions.go
new file mode 100644
index 0000000..f43bb9f
--- /dev/null
+++ b/vendor/github.com/mongodb/mongo-go-driver/mongo/options/estimatedcountoptions.go
@@ -0,0 +1,42 @@
+// Copyright (C) MongoDB, Inc. 2017-present.
+//
+// Licensed under the Apache License, Version 2.0 (the "License"); you may
+// not use this file except in compliance with the License. You may obtain
+// a copy of the License at http://www.apache.org/licenses/LICENSE-2.0
+
+package options
+
+import "time"
+
+// EstimatedDocumentCountOptions represents all possible options to the estimatedDocumentCount() function
+type EstimatedDocumentCountOptions struct {
+	MaxTime *time.Duration // The maximum amount of time to allow the operation to run
+}
+
+// EstimatedDocumentCount returns a pointer to a new EstimatedDocumentCountOptions
+func EstimatedDocumentCount() *EstimatedDocumentCountOptions {
+	return &EstimatedDocumentCountOptions{}
+}
+
+// SetMaxTime specifies the maximum amount of time to allow the operation to run
+func (eco *EstimatedDocumentCountOptions) SetMaxTime(d time.Duration) *EstimatedDocumentCountOptions {
+	eco.MaxTime = &d
+	return eco
+}
+
+// MergeEstimatedDocumentCountOptions combines the given *EstimatedDocumentCountOptions into a single
+// *EstimatedDocumentCountOptions in a last one wins fashion.
+func MergeEstimatedDocumentCountOptions(opts ...*EstimatedDocumentCountOptions) *EstimatedDocumentCountOptions {
+	e := EstimatedDocumentCount()
+	for _, opt := range opts {
+		if opt == nil {
+			continue
+		}
+
+		if opt.MaxTime != nil {
+			e.MaxTime = opt.MaxTime
+		}
+	}
+
+	return e
+}
diff --git a/vendor/github.com/mongodb/mongo-go-driver/mongo/options/findoptions.go b/vendor/github.com/mongodb/mongo-go-driver/mongo/options/findoptions.go
new file mode 100644
index 0000000..4ba6133
--- /dev/null
+++ b/vendor/github.com/mongodb/mongo-go-driver/mongo/options/findoptions.go
@@ -0,0 +1,693 @@
+// Copyright (C) MongoDB, Inc. 2017-present.
+//
+// Licensed under the Apache License, Version 2.0 (the "License"); you may
+// not use this file except in compliance with the License. You may obtain
+// a copy of the License at http://www.apache.org/licenses/LICENSE-2.0
+
+package options
+
+import (
+	"time"
+)
+
+// FindOptions represent all possible options to the find() function.
+type FindOptions struct {
+	AllowPartialResults *bool          // If true, allows partial results to be returned if some shards are down.
+	BatchSize           *int32         // Specifies the number of documents to return in every batch.
+	Collation           *Collation     // Specifies a collation to be used
+	Comment             *string        // Specifies a string to help trace the operation through the database.
+	CursorType          *CursorType    // Specifies the type of cursor to use
+	Hint                interface{}    // Specifies the index to use.
+	Limit               *int64         // Sets a limit on the number of results to return.
+	Max                 interface{}    // Sets an exclusive upper bound for a specific index
+	MaxAwaitTime        *time.Duration // Specifies the maximum amount of time for the server to wait on new documents.
+	MaxTime             *time.Duration // Specifies the maximum amount of time to allow the query to run.
+	Min                 interface{}    // Specifies the inclusive lower bound for a specific index.
+	NoCursorTimeout     *bool          // If true, prevents cursors from timing out after an inactivity period.
+	OplogReplay         *bool          // Adds an option for internal use only and should not be set.
+	Projection          interface{}    // Limits the fields returned for all documents.
+	ReturnKey           *bool          // If true, only returns index keys for all result documents.
+	ShowRecordID        *bool          // If true, a $recordId field with the record identifier will be added to the returned documents.
+	Skip                *int64         // Specifies the number of documents to skip before returning
+	Snapshot            *bool          // If true, prevents the cursor from returning a document more than once because of an intervening write operation.
+	Sort                interface{}    // Specifies the order in which to return results.
+}
+
+// Find creates a new FindOptions instance.
+func Find() *FindOptions {
+	return &FindOptions{}
+}
+
+// SetAllowPartialResults sets whether partial results can be returned if some shards are down.
+// For server versions < 3.2, this defaults to false.
+func (f *FindOptions) SetAllowPartialResults(b bool) *FindOptions {
+	f.AllowPartialResults = &b
+	return f
+}
+
+// SetBatchSize sets the number of documents to return in each batch.
+func (f *FindOptions) SetBatchSize(i int32) *FindOptions {
+	f.BatchSize = &i
+	return f
+}
+
+// SetCollation specifies a Collation to use for the Find operation.
+// Valid for server versions >= 3.4
+func (f *FindOptions) SetCollation(collation *Collation) *FindOptions {
+	f.Collation = collation
+	return f
+}
+
+// SetComment specifies a string to help trace the operation through the database.
+func (f *FindOptions) SetComment(comment string) *FindOptions {
+	f.Comment = &comment
+	return f
+}
+
+// SetCursorType specifes the type of cursor to use.
+func (f *FindOptions) SetCursorType(ct CursorType) *FindOptions {
+	f.CursorType = &ct
+	return f
+}
+
+// SetHint specifies the index to use.
+func (f *FindOptions) SetHint(hint interface{}) *FindOptions {
+	f.Hint = hint
+	return f
+}
+
+// SetLimit specifies a limit on the number of results.
+// A negative limit implies that only 1 batch should be returned.
+func (f *FindOptions) SetLimit(i int64) *FindOptions {
+	f.Limit = &i
+	return f
+}
+
+// SetMax specifies an exclusive upper bound for a specific index.
+func (f *FindOptions) SetMax(max interface{}) *FindOptions {
+	f.Max = max
+	return f
+}
+
+// SetMaxAwaitTime specifies the max amount of time for the server to wait on new documents.
+// If the cursor type is not TailableAwait, this option is ignored.
+// For server versions < 3.2, this option is ignored.
+func (f *FindOptions) SetMaxAwaitTime(d time.Duration) *FindOptions {
+	f.MaxAwaitTime = &d
+	return f
+}
+
+// SetMaxTime specifies the max time to allow the query to run.
+func (f *FindOptions) SetMaxTime(d time.Duration) *FindOptions {
+	f.MaxTime = &d
+	return f
+}
+
+// SetMin specifies the inclusive lower bound for a specific index.
+func (f *FindOptions) SetMin(min interface{}) *FindOptions {
+	f.Min = min
+	return f
+}
+
+// SetNoCursorTimeout specifies whether or not cursors should time out after a period of inactivity.
+// For server versions < 3.2, this defaults to false.
+func (f *FindOptions) SetNoCursorTimeout(b bool) *FindOptions {
+	f.NoCursorTimeout = &b
+	return f
+}
+
+// SetOplogReplay adds an option for internal use only and should not be set.
+// For server versions < 3.2, this defaults to false.
+func (f *FindOptions) SetOplogReplay(b bool) *FindOptions {
+	f.OplogReplay = &b
+	return f
+}
+
+// SetProjection adds an option to limit the fields returned for all documents.
+func (f *FindOptions) SetProjection(projection interface{}) *FindOptions {
+	f.Projection = projection
+	return f
+}
+
+// SetReturnKey adds an option to only return index keys for all result documents.
+func (f *FindOptions) SetReturnKey(b bool) *FindOptions {
+	f.ReturnKey = &b
+	return f
+}
+
+// SetShowRecordID adds an option to determine whether to return the record identifier for each document.
+// If true, a $recordId field will be added to each returned document.
+func (f *FindOptions) SetShowRecordID(b bool) *FindOptions {
+	f.ShowRecordID = &b
+	return f
+}
+
+// SetSkip specifies the number of documents to skip before returning.
+// For server versions < 3.2, this defaults to 0.
+func (f *FindOptions) SetSkip(i int64) *FindOptions {
+	f.Skip = &i
+	return f
+}
+
+// SetSnapshot prevents the cursor from returning a document more than once because of an intervening write operation.
+func (f *FindOptions) SetSnapshot(b bool) *FindOptions {
+	f.Snapshot = &b
+	return f
+}
+
+// SetSort specifies the order in which to return documents.
+func (f *FindOptions) SetSort(sort interface{}) *FindOptions {
+	f.Sort = sort
+	return f
+}
+
+// MergeFindOptions combines the argued FindOptions into a single FindOptions in a last-one-wins fashion
+func MergeFindOptions(opts ...*FindOptions) *FindOptions {
+	fo := Find()
+	for _, opt := range opts {
+		if opt == nil {
+			continue
+		}
+		if opt.AllowPartialResults != nil {
+			fo.AllowPartialResults = opt.AllowPartialResults
+		}
+		if opt.BatchSize != nil {
+			fo.BatchSize = opt.BatchSize
+		}
+		if opt.Collation != nil {
+			fo.Collation = opt.Collation
+		}
+		if opt.Comment != nil {
+			fo.Comment = opt.Comment
+		}
+		if opt.CursorType != nil {
+			fo.CursorType = opt.CursorType
+		}
+		if opt.Hint != nil {
+			fo.Hint = opt.Hint
+		}
+		if opt.Limit != nil {
+			fo.Limit = opt.Limit
+		}
+		if opt.Max != nil {
+			fo.Max = opt.Max
+		}
+		if opt.MaxAwaitTime != nil {
+			fo.MaxAwaitTime = opt.MaxAwaitTime
+		}
+		if opt.MaxTime != nil {
+			fo.MaxTime = opt.MaxTime
+		}
+		if opt.Min != nil {
+			fo.Min = opt.Min
+		}
+		if opt.NoCursorTimeout != nil {
+			fo.NoCursorTimeout = opt.NoCursorTimeout
+		}
+		if opt.OplogReplay != nil {
+			fo.OplogReplay = opt.OplogReplay
+		}
+		if opt.Projection != nil {
+			fo.Projection = opt.Projection
+		}
+		if opt.ReturnKey != nil {
+			fo.ReturnKey = opt.ReturnKey
+		}
+		if opt.ShowRecordID != nil {
+			fo.ShowRecordID = opt.ShowRecordID
+		}
+		if opt.Skip != nil {
+			fo.Skip = opt.Skip
+		}
+		if opt.Snapshot != nil {
+			fo.Snapshot = opt.Snapshot
+		}
+		if opt.Sort != nil {
+			fo.Sort = opt.Sort
+		}
+	}
+
+	return fo
+}
+
+// FindOneOptions represent all possible options to the findOne() function.
+type FindOneOptions struct {
+	AllowPartialResults *bool          // If true, allows partial results to be returned if some shards are down.
+	BatchSize           *int32         // Specifies the number of documents to return in every batch.
+	Collation           *Collation     // Specifies a collation to be used
+	Comment             *string        // Specifies a string to help trace the operation through the database.
+	CursorType          *CursorType    // Specifies the type of cursor to use
+	Hint                interface{}    // Specifies the index to use.
+	Max                 interface{}    // Sets an exclusive upper bound for a specific index
+	MaxAwaitTime        *time.Duration // Specifies the maximum amount of time for the server to wait on new documents.
+	MaxTime             *time.Duration // Specifies the maximum amount of time to allow the query to run.
+	Min                 interface{}    // Specifies the inclusive lower bound for a specific index.
+	NoCursorTimeout     *bool          // If true, prevents cursors from timing out after an inactivity period.
+	OplogReplay         *bool          // Adds an option for internal use only and should not be set.
+	Projection          interface{}    // Limits the fields returned for all documents.
+	ReturnKey           *bool          // If true, only returns index keys for all result documents.
+	ShowRecordID        *bool          // If true, a $recordId field with the record identifier will be added to the returned documents.
+	Skip                *int64         // Specifies the number of documents to skip before returning
+	Snapshot            *bool          // If true, prevents the cursor from returning a document more than once because of an intervening write operation.
+	Sort                interface{}    // Specifies the order in which to return results.
+}
+
+// FindOne creates a new FindOneOptions instance.
+func FindOne() *FindOneOptions {
+	return &FindOneOptions{}
+}
+
+// SetAllowPartialResults sets whether partial results can be returned if some shards are down.
+func (f *FindOneOptions) SetAllowPartialResults(b bool) *FindOneOptions {
+	f.AllowPartialResults = &b
+	return f
+}
+
+// SetBatchSize sets the number of documents to return in each batch.
+func (f *FindOneOptions) SetBatchSize(i int32) *FindOneOptions {
+	f.BatchSize = &i
+	return f
+}
+
+// SetCollation specifies a Collation to use for the Find operation.
+func (f *FindOneOptions) SetCollation(collation *Collation) *FindOneOptions {
+	f.Collation = collation
+	return f
+}
+
+// SetComment specifies a string to help trace the operation through the database.
+func (f *FindOneOptions) SetComment(comment string) *FindOneOptions {
+	f.Comment = &comment
+	return f
+}
+
+// SetCursorType specifes the type of cursor to use.
+func (f *FindOneOptions) SetCursorType(ct CursorType) *FindOneOptions {
+	f.CursorType = &ct
+	return f
+}
+
+// SetHint specifies the index to use.
+func (f *FindOneOptions) SetHint(hint interface{}) *FindOneOptions {
+	f.Hint = hint
+	return f
+}
+
+// SetMax specifies an exclusive upper bound for a specific index.
+func (f *FindOneOptions) SetMax(max interface{}) *FindOneOptions {
+	f.Max = max
+	return f
+}
+
+// SetMaxAwaitTime specifies the max amount of time for the server to wait on new documents.
+// For server versions < 3.2, this option is ignored.
+func (f *FindOneOptions) SetMaxAwaitTime(d time.Duration) *FindOneOptions {
+	f.MaxAwaitTime = &d
+	return f
+}
+
+// SetMaxTime specifies the max time to allow the query to run.
+func (f *FindOneOptions) SetMaxTime(d time.Duration) *FindOneOptions {
+	f.MaxTime = &d
+	return f
+}
+
+// SetMin specifies the inclusive lower bound for a specific index.
+func (f *FindOneOptions) SetMin(min interface{}) *FindOneOptions {
+	f.Min = min
+	return f
+}
+
+// SetNoCursorTimeout specifies whether or not cursors should time out after a period of inactivity.
+func (f *FindOneOptions) SetNoCursorTimeout(b bool) *FindOneOptions {
+	f.NoCursorTimeout = &b
+	return f
+}
+
+// SetOplogReplay adds an option for internal use only and should not be set.
+func (f *FindOneOptions) SetOplogReplay(b bool) *FindOneOptions {
+	f.OplogReplay = &b
+	return f
+}
+
+// SetProjection adds an option to limit the fields returned for all documents.
+func (f *FindOneOptions) SetProjection(projection interface{}) *FindOneOptions {
+	f.Projection = projection
+	return f
+}
+
+// SetReturnKey adds an option to only return index keys for all result documents.
+func (f *FindOneOptions) SetReturnKey(b bool) *FindOneOptions {
+	f.ReturnKey = &b
+	return f
+}
+
+// SetShowRecordID adds an option to determine whether to return the record identifier for each document.
+// If true, a $recordId field will be added to each returned document.
+func (f *FindOneOptions) SetShowRecordID(b bool) *FindOneOptions {
+	f.ShowRecordID = &b
+	return f
+}
+
+// SetSkip specifies the number of documents to skip before returning.
+func (f *FindOneOptions) SetSkip(i int64) *FindOneOptions {
+	f.Skip = &i
+	return f
+}
+
+// SetSnapshot prevents the cursor from returning a document more than once because of an intervening write operation.
+func (f *FindOneOptions) SetSnapshot(b bool) *FindOneOptions {
+	f.Snapshot = &b
+	return f
+}
+
+// SetSort specifies the order in which to return documents.
+func (f *FindOneOptions) SetSort(sort interface{}) *FindOneOptions {
+	f.Sort = sort
+	return f
+}
+
+// MergeFindOneOptions combines the argued FindOneOptions into a single FindOneOptions in a last-one-wins fashion
+func MergeFindOneOptions(opts ...*FindOneOptions) *FindOneOptions {
+	fo := FindOne()
+	for _, opt := range opts {
+		if opt == nil {
+			continue
+		}
+		if opt.AllowPartialResults != nil {
+			fo.AllowPartialResults = opt.AllowPartialResults
+		}
+		if opt.BatchSize != nil {
+			fo.BatchSize = opt.BatchSize
+		}
+		if opt.Collation != nil {
+			fo.Collation = opt.Collation
+		}
+		if opt.Comment != nil {
+			fo.Comment = opt.Comment
+		}
+		if opt.CursorType != nil {
+			fo.CursorType = opt.CursorType
+		}
+		if opt.Hint != nil {
+			fo.Hint = opt.Hint
+		}
+		if opt.Max != nil {
+			fo.Max = opt.Max
+		}
+		if opt.MaxAwaitTime != nil {
+			fo.MaxAwaitTime = opt.MaxAwaitTime
+		}
+		if opt.MaxTime != nil {
+			fo.MaxTime = opt.MaxTime
+		}
+		if opt.Min != nil {
+			fo.Min = opt.Min
+		}
+		if opt.NoCursorTimeout != nil {
+			fo.NoCursorTimeout = opt.NoCursorTimeout
+		}
+		if opt.OplogReplay != nil {
+			fo.OplogReplay = opt.OplogReplay
+		}
+		if opt.Projection != nil {
+			fo.Projection = opt.Projection
+		}
+		if opt.ReturnKey != nil {
+			fo.ReturnKey = opt.ReturnKey
+		}
+		if opt.ShowRecordID != nil {
+			fo.ShowRecordID = opt.ShowRecordID
+		}
+		if opt.Skip != nil {
+			fo.Skip = opt.Skip
+		}
+		if opt.Snapshot != nil {
+			fo.Snapshot = opt.Snapshot
+		}
+		if opt.Sort != nil {
+			fo.Sort = opt.Sort
+		}
+	}
+
+	return fo
+}
+
+// FindOneAndReplaceOptions represent all possible options to the findOne() function.
+type FindOneAndReplaceOptions struct {
+	BypassDocumentValidation *bool           // If true, allows the write to opt out of document-level validation.
+	Collation                *Collation      // Specifies a collation to be used
+	MaxTime                  *time.Duration  // Specifies the maximum amount of time to allow the query to run.
+	Projection               interface{}     // Limits the fields returned for all documents.
+	ReturnDocument           *ReturnDocument // Specifies whether the original or updated document should be returned.
+	Sort                     interface{}     // Specifies the order in which to return results.
+	Upsert                   *bool           // If true, creates a a new document if no document matches the query.
+}
+
+// FindOneAndReplace creates a new FindOneAndReplaceOptions instance.
+func FindOneAndReplace() *FindOneAndReplaceOptions {
+	return &FindOneAndReplaceOptions{}
+}
+
+// SetBypassDocumentValidation specifies whether or not the write should opt out of document-level validation.
+// Valid for server versions >= 3.2. For servers < 3.2, this option is ignored.
+func (f *FindOneAndReplaceOptions) SetBypassDocumentValidation(b bool) *FindOneAndReplaceOptions {
+	f.BypassDocumentValidation = &b
+	return f
+}
+
+// SetCollation specifies a Collation to use for the Find operation.
+func (f *FindOneAndReplaceOptions) SetCollation(collation *Collation) *FindOneAndReplaceOptions {
+	f.Collation = collation
+	return f
+}
+
+// SetMaxTime specifies the max time to allow the query to run.
+func (f *FindOneAndReplaceOptions) SetMaxTime(d time.Duration) *FindOneAndReplaceOptions {
+	f.MaxTime = &d
+	return f
+}
+
+// SetProjection adds an option to limit the fields returned for all documents.
+func (f *FindOneAndReplaceOptions) SetProjection(projection interface{}) *FindOneAndReplaceOptions {
+	f.Projection = projection
+	return f
+}
+
+// SetReturnDocument specifies whether the original or updated document should be returned.
+// If set to Before, the original document will be returned. If set to After, the updated document
+// will be returned.
+func (f *FindOneAndReplaceOptions) SetReturnDocument(rd ReturnDocument) *FindOneAndReplaceOptions {
+	f.ReturnDocument = &rd
+	return f
+}
+
+// SetSort specifies the order in which to return documents.
+func (f *FindOneAndReplaceOptions) SetSort(sort interface{}) *FindOneAndReplaceOptions {
+	f.Sort = sort
+	return f
+}
+
+// SetUpsert specifies if a new document should be created if no document matches the query.
+func (f *FindOneAndReplaceOptions) SetUpsert(b bool) *FindOneAndReplaceOptions {
+	f.Upsert = &b
+	return f
+}
+
+// MergeFindOneAndReplaceOptions combines the argued FindOneAndReplaceOptions into a single FindOneAndReplaceOptions in a last-one-wins fashion
+func MergeFindOneAndReplaceOptions(opts ...*FindOneAndReplaceOptions) *FindOneAndReplaceOptions {
+	fo := FindOneAndReplace()
+	for _, opt := range opts {
+		if opt == nil {
+			continue
+		}
+		if opt.BypassDocumentValidation != nil {
+			fo.BypassDocumentValidation = opt.BypassDocumentValidation
+		}
+		if opt.Collation != nil {
+			fo.Collation = opt.Collation
+		}
+		if opt.MaxTime != nil {
+			fo.MaxTime = opt.MaxTime
+		}
+		if opt.Projection != nil {
+			fo.Projection = opt.Projection
+		}
+		if opt.ReturnDocument != nil {
+			fo.ReturnDocument = opt.ReturnDocument
+		}
+		if opt.Sort != nil {
+			fo.Sort = opt.Sort
+		}
+		if opt.Upsert != nil {
+			fo.Upsert = opt.Upsert
+		}
+	}
+
+	return fo
+}
+
+// FindOneAndUpdateOptions represent all possible options to the findOne() function.
+type FindOneAndUpdateOptions struct {
+	ArrayFilters             *ArrayFilters   // A set of filters specifying to which array elements an update should apply.
+	BypassDocumentValidation *bool           // If true, allows the write to opt out of document-level validation.
+	Collation                *Collation      // Specifies a collation to be used
+	MaxTime                  *time.Duration  // Specifies the maximum amount of time to allow the query to run.
+	Projection               interface{}     // Limits the fields returned for all documents.
+	ReturnDocument           *ReturnDocument // Specifies whether the original or updated document should be returned.
+	Sort                     interface{}     // Specifies the order in which to return results.
+	Upsert                   *bool           // If true, creates a a new document if no document matches the query.
+}
+
+// FindOneAndUpdate creates a new FindOneAndUpdateOptions instance.
+func FindOneAndUpdate() *FindOneAndUpdateOptions {
+	return &FindOneAndUpdateOptions{}
+}
+
+// SetBypassDocumentValidation sets filters that specify to which array elements an update should apply.
+func (f *FindOneAndUpdateOptions) SetBypassDocumentValidation(b bool) *FindOneAndUpdateOptions {
+	f.BypassDocumentValidation = &b
+	return f
+}
+
+// SetArrayFilters specifies a set of filters, which
+func (f *FindOneAndUpdateOptions) SetArrayFilters(filters ArrayFilters) *FindOneAndUpdateOptions {
+	f.ArrayFilters = &filters
+	return f
+}
+
+// SetCollation specifies a Collation to use for the Find operation.
+func (f *FindOneAndUpdateOptions) SetCollation(collation *Collation) *FindOneAndUpdateOptions {
+	f.Collation = collation
+	return f
+}
+
+// SetMaxTime specifies the max time to allow the query to run.
+func (f *FindOneAndUpdateOptions) SetMaxTime(d time.Duration) *FindOneAndUpdateOptions {
+	f.MaxTime = &d
+	return f
+}
+
+// SetProjection adds an option to limit the fields returned for all documents.
+func (f *FindOneAndUpdateOptions) SetProjection(projection interface{}) *FindOneAndUpdateOptions {
+	f.Projection = projection
+	return f
+}
+
+// SetReturnDocument specifies whether the original or updated document should be returned.
+// If set to Before, the original document will be returned. If set to After, the updated document
+// will be returned.
+func (f *FindOneAndUpdateOptions) SetReturnDocument(rd ReturnDocument) *FindOneAndUpdateOptions {
+	f.ReturnDocument = &rd
+	return f
+}
+
+// SetSort specifies the order in which to return documents.
+func (f *FindOneAndUpdateOptions) SetSort(sort interface{}) *FindOneAndUpdateOptions {
+	f.Sort = sort
+	return f
+}
+
+// SetUpsert specifies if a new document should be created if no document matches the query.
+func (f *FindOneAndUpdateOptions) SetUpsert(b bool) *FindOneAndUpdateOptions {
+	f.Upsert = &b
+	return f
+}
+
+// MergeFindOneAndUpdateOptions combines the argued FindOneAndUpdateOptions into a single FindOneAndUpdateOptions in a last-one-wins fashion
+func MergeFindOneAndUpdateOptions(opts ...*FindOneAndUpdateOptions) *FindOneAndUpdateOptions {
+	fo := FindOneAndUpdate()
+	for _, opt := range opts {
+		if opt == nil {
+			continue
+		}
+		if opt.ArrayFilters != nil {
+			fo.ArrayFilters = opt.ArrayFilters
+		}
+		if opt.BypassDocumentValidation != nil {
+			fo.BypassDocumentValidation = opt.BypassDocumentValidation
+		}
+		if opt.Collation != nil {
+			fo.Collation = opt.Collation
+		}
+		if opt.MaxTime != nil {
+			fo.MaxTime = opt.MaxTime
+		}
+		if opt.Projection != nil {
+			fo.Projection = opt.Projection
+		}
+		if opt.ReturnDocument != nil {
+			fo.ReturnDocument = opt.ReturnDocument
+		}
+		if opt.Sort != nil {
+			fo.Sort = opt.Sort
+		}
+		if opt.Upsert != nil {
+			fo.Upsert = opt.Upsert
+		}
+	}
+
+	return fo
+}
+
+// FindOneAndDeleteOptions represent all possible options to the findOne() function.
+type FindOneAndDeleteOptions struct {
+	Collation  *Collation     // Specifies a collation to be used
+	MaxTime    *time.Duration // Specifies the maximum amount of time to allow the query to run.
+	Projection interface{}    // Limits the fields returned for all documents.
+	Sort       interface{}    // Specifies the order in which to return results.
+}
+
+// FindOneAndDelete creates a new FindOneAndDeleteOptions instance.
+func FindOneAndDelete() *FindOneAndDeleteOptions {
+	return &FindOneAndDeleteOptions{}
+}
+
+// SetCollation specifies a Collation to use for the Find operation.
+// Valid for server versions >= 3.4
+func (f *FindOneAndDeleteOptions) SetCollation(collation *Collation) *FindOneAndDeleteOptions {
+	f.Collation = collation
+	return f
+}
+
+// SetMaxTime specifies the max time to allow the query to run.
+func (f *FindOneAndDeleteOptions) SetMaxTime(d time.Duration) *FindOneAndDeleteOptions {
+	f.MaxTime = &d
+	return f
+}
+
+// SetProjection adds an option to limit the fields returned for all documents.
+func (f *FindOneAndDeleteOptions) SetProjection(projection interface{}) *FindOneAndDeleteOptions {
+	f.Projection = projection
+	return f
+}
+
+// SetSort specifies the order in which to return documents.
+func (f *FindOneAndDeleteOptions) SetSort(sort interface{}) *FindOneAndDeleteOptions {
+	f.Sort = sort
+	return f
+}
+
+// MergeFindOneAndDeleteOptions combines the argued FindOneAndDeleteOptions into a single FindOneAndDeleteOptions in a last-one-wins fashion
+func MergeFindOneAndDeleteOptions(opts ...*FindOneAndDeleteOptions) *FindOneAndDeleteOptions {
+	fo := FindOneAndDelete()
+	for _, opt := range opts {
+		if opt == nil {
+			continue
+		}
+		if opt.Collation != nil {
+			fo.Collation = opt.Collation
+		}
+		if opt.MaxTime != nil {
+			fo.MaxTime = opt.MaxTime
+		}
+		if opt.Projection != nil {
+			fo.Projection = opt.Projection
+		}
+		if opt.Sort != nil {
+			fo.Sort = opt.Sort
+		}
+	}
+
+	return fo
+}
diff --git a/vendor/github.com/mongodb/mongo-go-driver/mongo/options/gridfsoptions.go b/vendor/github.com/mongodb/mongo-go-driver/mongo/options/gridfsoptions.go
new file mode 100644
index 0000000..232a1c8
--- /dev/null
+++ b/vendor/github.com/mongodb/mongo-go-driver/mongo/options/gridfsoptions.go
@@ -0,0 +1,268 @@
+// Copyright (C) MongoDB, Inc. 2017-present.
+//
+// Licensed under the Apache License, Version 2.0 (the "License"); you may
+// not use this file except in compliance with the License. You may obtain
+// a copy of the License at http://www.apache.org/licenses/LICENSE-2.0
+
+package options
+
+import (
+	"time"
+
+	"github.com/mongodb/mongo-go-driver/mongo/readconcern"
+	"github.com/mongodb/mongo-go-driver/mongo/readpref"
+	"github.com/mongodb/mongo-go-driver/mongo/writeconcern"
+	"github.com/mongodb/mongo-go-driver/x/bsonx"
+)
+
+// DefaultName is the default name for a GridFS bucket.
+var DefaultName = "fs"
+
+// DefaultChunkSize is the default size of each file chunk in bytes.
+var DefaultChunkSize int32 = 255 * 1000
+
+// DefaultRevision is the default revision number for a download by name operation.
+var DefaultRevision int32 = -1
+
+// BucketOptions represents all possible options to configure a GridFS bucket.
+type BucketOptions struct {
+	Name           *string                    // The bucket name. Defaults to "fs".
+	ChunkSizeBytes *int32                     // The chunk size in bytes. Defaults to 255KB.
+	WriteConcern   *writeconcern.WriteConcern // The write concern for the bucket. Defaults to the write concern of the database.
+	ReadConcern    *readconcern.ReadConcern   // The read concern for the bucket. Defaults to the read concern of the database.
+	ReadPreference *readpref.ReadPref         // The read preference for the bucket. Defaults to the read preference of the database.
+}
+
+// GridFSBucket creates a new *BucketOptions
+func GridFSBucket() *BucketOptions {
+	return &BucketOptions{
+		Name:           &DefaultName,
+		ChunkSizeBytes: &DefaultChunkSize,
+	}
+}
+
+// SetName sets the name for the bucket. Defaults to "fs" if not set.
+func (b *BucketOptions) SetName(name string) *BucketOptions {
+	b.Name = &name
+	return b
+}
+
+// SetChunkSizeBytes sets the chunk size in bytes for the bucket. Defaults to 255KB if not set.
+func (b *BucketOptions) SetChunkSizeBytes(i int32) *BucketOptions {
+	b.ChunkSizeBytes = &i
+	return b
+}
+
+// SetWriteConcern sets the write concern for the bucket.
+func (b *BucketOptions) SetWriteConcern(wc *writeconcern.WriteConcern) *BucketOptions {
+	b.WriteConcern = wc
+	return b
+}
+
+// SetReadConcern sets the read concern for the bucket.
+func (b *BucketOptions) SetReadConcern(rc *readconcern.ReadConcern) *BucketOptions {
+	b.ReadConcern = rc
+	return b
+}
+
+// SetReadPreference sets the read preference for the bucket.
+func (b *BucketOptions) SetReadPreference(rp *readpref.ReadPref) *BucketOptions {
+	b.ReadPreference = rp
+	return b
+}
+
+// MergeBucketOptions combines the given *BucketOptions into a single *BucketOptions.
+// If the name or chunk size is not set in any of the given *BucketOptions, the resulting *BucketOptions will have
+// name "fs" and chunk size 255KB.
+func MergeBucketOptions(opts ...*BucketOptions) *BucketOptions {
+	b := GridFSBucket()
+
+	for _, opt := range opts {
+		if opt == nil {
+			continue
+		}
+		if opt.Name != nil {
+			b.Name = opt.Name
+		}
+		if opt.ChunkSizeBytes != nil {
+			b.ChunkSizeBytes = opt.ChunkSizeBytes
+		}
+		if opt.WriteConcern != nil {
+			b.WriteConcern = opt.WriteConcern
+		}
+		if opt.ReadConcern != nil {
+			b.ReadConcern = opt.ReadConcern
+		}
+		if opt.ReadPreference != nil {
+			b.ReadPreference = opt.ReadPreference
+		}
+	}
+
+	return b
+}
+
+// UploadOptions represents all possible options for a GridFS upload operation.
+type UploadOptions struct {
+	ChunkSizeBytes *int32    // Chunk size in bytes. Defaults to the chunk size of the bucket.
+	Metadata       bsonx.Doc // User data for the 'metadata' field of the files collection document.
+}
+
+// GridFSUpload creates a new *UploadOptions
+func GridFSUpload() *UploadOptions {
+	return &UploadOptions{}
+}
+
+// SetChunkSizeBytes sets the chunk size in bytes for the upload. Defaults to 255KB if not set.
+func (u *UploadOptions) SetChunkSizeBytes(i int32) *UploadOptions {
+	u.ChunkSizeBytes = &i
+	return u
+}
+
+// SetMetadata specfies the metadata for the upload.
+func (u *UploadOptions) SetMetadata(doc bsonx.Doc) *UploadOptions {
+	u.Metadata = doc
+	return u
+}
+
+// MergeUploadOptions combines the given *UploadOptions into a single *UploadOptions.
+// If the chunk size is not set in any of the given *UploadOptions, the resulting *UploadOptions will have chunk size
+// 255KB.
+func MergeUploadOptions(opts ...*UploadOptions) *UploadOptions {
+	u := GridFSUpload()
+
+	for _, opt := range opts {
+		if opt == nil {
+			continue
+		}
+		if opt.ChunkSizeBytes != nil {
+			u.ChunkSizeBytes = opt.ChunkSizeBytes
+		}
+		if opt.Metadata != nil {
+			u.Metadata = opt.Metadata
+		}
+	}
+
+	return u
+}
+
+// NameOptions represents all options that can be used for a GridFS download by name operation.
+type NameOptions struct {
+	Revision *int32 // Which revision (documents with the same filename and different uploadDate). Defaults to -1 (the most recent revision).
+}
+
+// GridFSName creates a new *NameOptions
+func GridFSName() *NameOptions {
+	return &NameOptions{}
+}
+
+// SetRevision specifies which revision of the file to retrieve. Defaults to -1.
+// * Revision numbers are defined as follows:
+// * 0 = the original stored file
+// * 1 = the first revision
+// * 2 = the second revision
+// * etc…
+// * -2 = the second most recent revision
+// * -1 = the most recent revision
+func (n *NameOptions) SetRevision(r int32) *NameOptions {
+	n.Revision = &r
+	return n
+}
+
+// MergeNameOptions combines the given *NameOptions into a single *NameOptions in a last one wins fashion.
+func MergeNameOptions(opts ...*NameOptions) *NameOptions {
+	n := GridFSName()
+	n.Revision = &DefaultRevision
+
+	for _, opt := range opts {
+		if opt == nil {
+			continue
+		}
+		if opt.Revision != nil {
+			n.Revision = opt.Revision
+		}
+	}
+
+	return n
+}
+
+// GridFSFindOptions represents all options for a GridFS find operation.
+type GridFSFindOptions struct {
+	BatchSize       *int32
+	Limit           *int32
+	MaxTime         *time.Duration
+	NoCursorTimeout *bool
+	Skip            *int32
+	Sort            interface{}
+}
+
+// GridFSFind creates a new GridFSFindOptions instance.
+func GridFSFind() *GridFSFindOptions {
+	return &GridFSFindOptions{}
+}
+
+// SetBatchSize sets the number of documents to return in each batch.
+func (f *GridFSFindOptions) SetBatchSize(i int32) *GridFSFindOptions {
+	f.BatchSize = &i
+	return f
+}
+
+// SetLimit specifies a limit on the number of results.
+// A negative limit implies that only 1 batch should be returned.
+func (f *GridFSFindOptions) SetLimit(i int32) *GridFSFindOptions {
+	f.Limit = &i
+	return f
+}
+
+// SetMaxTime specifies the max time to allow the query to run.
+func (f *GridFSFindOptions) SetMaxTime(d time.Duration) *GridFSFindOptions {
+	f.MaxTime = &d
+	return f
+}
+
+// SetNoCursorTimeout specifies whether or not cursors should time out after a period of inactivity.
+func (f *GridFSFindOptions) SetNoCursorTimeout(b bool) *GridFSFindOptions {
+	f.NoCursorTimeout = &b
+	return f
+}
+
+// SetSkip specifies the number of documents to skip before returning.
+func (f *GridFSFindOptions) SetSkip(i int32) *GridFSFindOptions {
+	f.Skip = &i
+	return f
+}
+
+// SetSort specifies the order in which to return documents.
+func (f *GridFSFindOptions) SetSort(sort interface{}) *GridFSFindOptions {
+	f.Sort = sort
+	return f
+}
+
+// MergeGridFSFindOptions combines the argued GridFSFindOptions into a single GridFSFindOptions in a last-one-wins fashion
+func MergeGridFSFindOptions(opts ...*GridFSFindOptions) *GridFSFindOptions {
+	fo := GridFSFind()
+	for _, opt := range opts {
+		if opt == nil {
+			continue
+		}
+		if opt.BatchSize != nil {
+			fo.BatchSize = opt.BatchSize
+		}
+		if opt.Limit != nil {
+			fo.Limit = opt.Limit
+		}
+		if opt.MaxTime != nil {
+			fo.MaxTime = opt.MaxTime
+		}
+		if opt.NoCursorTimeout != nil {
+			fo.NoCursorTimeout = opt.NoCursorTimeout
+		}
+		if opt.Skip != nil {
+			fo.Skip = opt.Skip
+		}
+		if opt.Sort != nil {
+			fo.Sort = opt.Sort
+		}
+	}
+
+	return fo
+}
diff --git a/vendor/github.com/mongodb/mongo-go-driver/mongo/options/indexoptions.go b/vendor/github.com/mongodb/mongo-go-driver/mongo/options/indexoptions.go
new file mode 100644
index 0000000..2fda698
--- /dev/null
+++ b/vendor/github.com/mongodb/mongo-go-driver/mongo/options/indexoptions.go
@@ -0,0 +1,326 @@
+// Copyright (C) MongoDB, Inc. 2017-present.
+//
+// Licensed under the Apache License, Version 2.0 (the "License"); you may
+// not use this file except in compliance with the License. You may obtain
+// a copy of the License at http://www.apache.org/licenses/LICENSE-2.0
+
+package options
+
+import (
+	"time"
+)
+
+// CreateIndexesOptions represents all possible options for the create() function.
+type CreateIndexesOptions struct {
+	MaxTime *time.Duration // The maximum amount of time to allow the query to run.
+}
+
+// CreateIndexes creates a new CreateIndexesOptions instance.
+func CreateIndexes() *CreateIndexesOptions {
+	return &CreateIndexesOptions{}
+}
+
+// SetMaxTime specifies the maximum amount of time to allow the query to run.
+func (c *CreateIndexesOptions) SetMaxTime(d time.Duration) *CreateIndexesOptions {
+	c.MaxTime = &d
+	return c
+}
+
+// MergeCreateIndexesOptions combines the given *CreateIndexesOptions into a single *CreateIndexesOptions in a last one
+// wins fashion.
+func MergeCreateIndexesOptions(opts ...*CreateIndexesOptions) *CreateIndexesOptions {
+	c := CreateIndexes()
+	for _, opt := range opts {
+		if opt == nil {
+			continue
+		}
+		if opt.MaxTime != nil {
+			c.MaxTime = opt.MaxTime
+		}
+	}
+
+	return c
+}
+
+// DropIndexesOptions represents all possible options for the create() function.
+type DropIndexesOptions struct {
+	MaxTime *time.Duration
+}
+
+// DropIndexes creates a new DropIndexesOptions instance.
+func DropIndexes() *DropIndexesOptions {
+	return &DropIndexesOptions{}
+}
+
+// SetMaxTime specifies the maximum amount of time to allow the query to run.
+func (d *DropIndexesOptions) SetMaxTime(duration time.Duration) *DropIndexesOptions {
+	d.MaxTime = &duration
+	return d
+}
+
+// MergeDropIndexesOptions combines the given *DropIndexesOptions into a single *DropIndexesOptions in a last one
+// wins fashion.
+func MergeDropIndexesOptions(opts ...*DropIndexesOptions) *DropIndexesOptions {
+	c := DropIndexes()
+	for _, opt := range opts {
+		if opt == nil {
+			continue
+		}
+		if opt.MaxTime != nil {
+			c.MaxTime = opt.MaxTime
+		}
+	}
+
+	return c
+}
+
+// ListIndexesOptions represents all possible options for the create() function.
+type ListIndexesOptions struct {
+	BatchSize *int32
+	MaxTime   *time.Duration
+}
+
+// ListIndexes creates a new ListIndexesOptions instance.
+func ListIndexes() *ListIndexesOptions {
+	return &ListIndexesOptions{}
+}
+
+// SetBatchSize specifies the number of documents to return in every batch.
+func (l *ListIndexesOptions) SetBatchSize(i int32) *ListIndexesOptions {
+	l.BatchSize = &i
+	return l
+}
+
+// SetMaxTime specifies the maximum amount of time to allow the query to run.
+func (l *ListIndexesOptions) SetMaxTime(d time.Duration) *ListIndexesOptions {
+	l.MaxTime = &d
+	return l
+}
+
+// MergeListIndexesOptions combines the given *ListIndexesOptions into a single *ListIndexesOptions in a last one
+// wins fashion.
+func MergeListIndexesOptions(opts ...*ListIndexesOptions) *ListIndexesOptions {
+	c := ListIndexes()
+	for _, opt := range opts {
+		if opt == nil {
+			continue
+		}
+		if opt.MaxTime != nil {
+			c.MaxTime = opt.MaxTime
+		}
+	}
+
+	return c
+}
+
+// IndexOptions represents all possible options to configure a new index.
+type IndexOptions struct {
+	Background              *bool
+	ExpireAfterSeconds      *int32
+	Name                    *string
+	Sparse                  *bool
+	StorageEngine           interface{}
+	Unique                  *bool
+	Version                 *int32
+	DefaultLanguage         *string
+	LanguageOverride        *string
+	TextVersion             *int32
+	Weights                 interface{}
+	SphereVersion           *int32
+	Bits                    *int32
+	Max                     *float64
+	Min                     *float64
+	BucketSize              *int32
+	PartialFilterExpression interface{}
+	Collation               *Collation
+}
+
+// Index creates a new *IndexOptions
+func Index() *IndexOptions {
+	return &IndexOptions{}
+}
+
+// SetBackground sets the background option. If true, the server will create the index in the background and not block
+// other tasks
+func (i *IndexOptions) SetBackground(background bool) *IndexOptions {
+	i.Background = &background
+	return i
+}
+
+// SetExpireAfterSeconds specifies the number of seconds for a document to remain in a collection.
+func (i *IndexOptions) SetExpireAfterSeconds(seconds int32) *IndexOptions {
+	i.ExpireAfterSeconds = &seconds
+	return i
+}
+
+// SetName specifies a name for the index.
+// If not set, a name will be generated in the format "[field]_[direction]".
+// If multiple indexes are created for the same key pattern with different collations, a name must be provided to avoid
+// ambiguity.
+func (i *IndexOptions) SetName(name string) *IndexOptions {
+	i.Name = &name
+	return i
+}
+
+// SetSparse sets the sparse option.
+// If true, the index will only reference documents with the specified field in the index.
+func (i *IndexOptions) SetSparse(sparse bool) *IndexOptions {
+	i.Sparse = &sparse
+	return i
+}
+
+// SetStorageEngine specifies the storage engine to use.
+// Valid for server versions >= 3.0
+func (i *IndexOptions) SetStorageEngine(engine interface{}) *IndexOptions {
+	i.StorageEngine = engine
+	return i
+}
+
+// SetUnique forces the index to be unique.
+func (i *IndexOptions) SetUnique(unique bool) *IndexOptions {
+	i.Unique = &unique
+	return i
+}
+
+// SetVersion specifies the index version number, either 0 or 1.
+func (i *IndexOptions) SetVersion(version int32) *IndexOptions {
+	i.Version = &version
+	return i
+}
+
+// SetDefaultLanguage specifies the default language for text indexes.
+// If not set, this will default to english.
+func (i *IndexOptions) SetDefaultLanguage(language string) *IndexOptions {
+	i.DefaultLanguage = &language
+	return i
+}
+
+// SetLanguageOverride specifies the field in the document to override the language.
+func (i *IndexOptions) SetLanguageOverride(override string) *IndexOptions {
+	i.LanguageOverride = &override
+	return i
+}
+
+// SetTextVersion specifies the text index version number.
+// MongoDB version 2.4 can only support version 1.
+// MongoDB versions 2.6 and higher can support versions 1 or 2.
+func (i *IndexOptions) SetTextVersion(version int32) *IndexOptions {
+	i.TextVersion = &version
+	return i
+}
+
+// SetWeights specifies fields in the index and their corresponding weight values.
+func (i *IndexOptions) SetWeights(weights interface{}) *IndexOptions {
+	i.Weights = weights
+	return i
+}
+
+// SetSphereVersion specifies the 2dsphere index version number.
+// MongoDB version 2.4 can only support version 1.
+// MongoDB versions 2.6 and higher can support versions 1 or 2.
+func (i *IndexOptions) SetSphereVersion(version int32) *IndexOptions {
+	i.SphereVersion = &version
+	return i
+}
+
+// SetBits specifies the precision of the stored geo hash in the 2d index, from 1 to 32.
+func (i *IndexOptions) SetBits(bits int32) *IndexOptions {
+	i.Bits = &bits
+	return i
+}
+
+// SetMax specifies the maximum boundary for latitude and longitude in the 2d index.
+func (i *IndexOptions) SetMax(max float64) *IndexOptions {
+	i.Max = &max
+	return i
+}
+
+// SetMin specifies the minimum boundary for latitude and longitude in the 2d index.
+func (i *IndexOptions) SetMin(min float64) *IndexOptions {
+	i.Min = &min
+	return i
+}
+
+// SetBucketSize specifies number of units within which to group the location values in a geo haystack index.
+func (i *IndexOptions) SetBucketSize(bucketSize int32) *IndexOptions {
+	i.BucketSize = &bucketSize
+	return i
+}
+
+// SetPartialFilterExpression specifies a filter for use in a partial index. Only documents that match the filter
+// expression are included in the index.
+func (i *IndexOptions) SetPartialFilterExpression(expression interface{}) *IndexOptions {
+	i.PartialFilterExpression = expression
+	return i
+}
+
+// SetCollation specifies a Collation to use for the operation.
+// Valid for server versions >= 3.4
+func (i *IndexOptions) SetCollation(collation *Collation) *IndexOptions {
+	i.Collation = collation
+	return i
+}
+
+// MergeIndexOptions combines the given *IndexOptions into a single *IndexOptions in a last one wins fashion.
+func MergeIndexOptions(opts ...*IndexOptions) *IndexOptions {
+	i := Index()
+
+	for _, opt := range opts {
+		if opt.Background != nil {
+			i.Background = opt.Background
+		}
+		if opt.ExpireAfterSeconds != nil {
+			i.ExpireAfterSeconds = opt.ExpireAfterSeconds
+		}
+		if opt.Name != nil {
+			i.Name = opt.Name
+		}
+		if opt.Sparse != nil {
+			i.Sparse = opt.Sparse
+		}
+		if opt.StorageEngine != nil {
+			i.StorageEngine = opt.StorageEngine
+		}
+		if opt.Unique != nil {
+			i.Unique = opt.Unique
+		}
+		if opt.Version != nil {
+			i.Version = opt.Version
+		}
+		if opt.DefaultLanguage != nil {
+			i.DefaultLanguage = opt.DefaultLanguage
+		}
+		if opt.LanguageOverride != nil {
+			i.LanguageOverride = opt.LanguageOverride
+		}
+		if opt.TextVersion != nil {
+			i.TextVersion = opt.TextVersion
+		}
+		if opt.Weights != nil {
+			i.Weights = opt.Weights
+		}
+		if opt.SphereVersion != nil {
+			i.SphereVersion = opt.SphereVersion
+		}
+		if opt.Bits != nil {
+			i.Bits = opt.Bits
+		}
+		if opt.Max != nil {
+			i.Max = opt.Max
+		}
+		if opt.Min != nil {
+			i.Min = opt.Min
+		}
+		if opt.BucketSize != nil {
+			i.BucketSize = opt.BucketSize
+		}
+		if opt.PartialFilterExpression != nil {
+			i.PartialFilterExpression = opt.PartialFilterExpression
+		}
+		if opt.Collation != nil {
+			i.Collation = opt.Collation
+		}
+	}
+
+	return i
+}
diff --git a/vendor/github.com/mongodb/mongo-go-driver/mongo/options/insertoptions.go b/vendor/github.com/mongodb/mongo-go-driver/mongo/options/insertoptions.go
new file mode 100644
index 0000000..064ede3
--- /dev/null
+++ b/vendor/github.com/mongodb/mongo-go-driver/mongo/options/insertoptions.go
@@ -0,0 +1,84 @@
+// Copyright (C) MongoDB, Inc. 2017-present.
+//
+// Licensed under the Apache License, Version 2.0 (the "License"); you may
+// not use this file except in compliance with the License. You may obtain
+// a copy of the License at http://www.apache.org/licenses/LICENSE-2.0
+
+package options
+
+// InsertOneOptions represents all possible options to the insertOne()
+type InsertOneOptions struct {
+	BypassDocumentValidation *bool // If true, allows the write to opt-out of document level validation
+}
+
+// InsertOne returns a pointer to a new InsertOneOptions
+func InsertOne() *InsertOneOptions {
+	return &InsertOneOptions{}
+}
+
+// SetBypassDocumentValidation allows the write to opt-out of document level validation.
+// Valid for server versions >= 3.2. For servers < 3.2, this option is ignored.
+func (ioo *InsertOneOptions) SetBypassDocumentValidation(b bool) *InsertOneOptions {
+	ioo.BypassDocumentValidation = &b
+	return ioo
+}
+
+// MergeInsertOneOptions combines the argued InsertOneOptions into a single InsertOneOptions in a last-one-wins fashion
+func MergeInsertOneOptions(opts ...*InsertOneOptions) *InsertOneOptions {
+	ioOpts := InsertOne()
+	for _, ioo := range opts {
+		if ioo == nil {
+			continue
+		}
+		if ioo.BypassDocumentValidation != nil {
+			ioOpts.BypassDocumentValidation = ioo.BypassDocumentValidation
+		}
+	}
+
+	return ioOpts
+}
+
+// InsertManyOptions represents all possible options to the insertMany()
+type InsertManyOptions struct {
+	BypassDocumentValidation *bool // If true, allows the write to opt-out of document level validation
+	Ordered                  *bool // If true, when an insert fails, return without performing the remaining inserts. Defaults to true.
+}
+
+// InsertMany returns a pointer to a new InsertManyOptions
+func InsertMany() *InsertManyOptions {
+	return &InsertManyOptions{
+		Ordered: &DefaultOrdered,
+	}
+}
+
+// SetBypassDocumentValidation allows the write to opt-out of document level validation.
+// Valid for server versions >= 3.2. For servers < 3.2, this option is ignored.
+func (imo *InsertManyOptions) SetBypassDocumentValidation(b bool) *InsertManyOptions {
+	imo.BypassDocumentValidation = &b
+	return imo
+}
+
+// SetOrdered configures the ordered option. If true, when a write fails, the function will return without attempting
+// remaining writes. Defaults to true.
+func (imo *InsertManyOptions) SetOrdered(b bool) *InsertManyOptions {
+	imo.Ordered = &b
+	return imo
+}
+
+// MergeInsertManyOptions combines the argued InsertManyOptions into a single InsertManyOptions in a last-one-wins fashion
+func MergeInsertManyOptions(opts ...*InsertManyOptions) *InsertManyOptions {
+	imOpts := InsertMany()
+	for _, imo := range opts {
+		if imo == nil {
+			continue
+		}
+		if imo.BypassDocumentValidation != nil {
+			imOpts.BypassDocumentValidation = imo.BypassDocumentValidation
+		}
+		if imo.Ordered != nil {
+			imOpts.Ordered = imo.Ordered
+		}
+	}
+
+	return imOpts
+}
diff --git a/vendor/github.com/mongodb/mongo-go-driver/mongo/options/listcollectionsoptions.go b/vendor/github.com/mongodb/mongo-go-driver/mongo/options/listcollectionsoptions.go
new file mode 100644
index 0000000..e44ad4a
--- /dev/null
+++ b/vendor/github.com/mongodb/mongo-go-driver/mongo/options/listcollectionsoptions.go
@@ -0,0 +1,39 @@
+// Copyright (C) MongoDB, Inc. 2017-present.
+//
+// Licensed under the Apache License, Version 2.0 (the "License"); you may
+// not use this file except in compliance with the License. You may obtain
+// a copy of the License at http://www.apache.org/licenses/LICENSE-2.0
+
+package options
+
+// ListCollectionsOptions represents all possible options for a listCollections command.
+type ListCollectionsOptions struct {
+	NameOnly *bool // If true, only the collection names will be returned.
+}
+
+// ListCollections creates a new *ListCollectionsOptions
+func ListCollections() *ListCollectionsOptions {
+	return &ListCollectionsOptions{}
+}
+
+// SetNameOnly specifies whether to return only the collection names.
+func (lc *ListCollectionsOptions) SetNameOnly(b bool) *ListCollectionsOptions {
+	lc.NameOnly = &b
+	return lc
+}
+
+// MergeListCollectionsOptions combines the given *ListCollectionsOptions into a single *ListCollectionsOptions in a
+// last one wins fashion.
+func MergeListCollectionsOptions(opts ...*ListCollectionsOptions) *ListCollectionsOptions {
+	lc := ListCollections()
+	for _, opt := range opts {
+		if opt == nil {
+			continue
+		}
+		if opt.NameOnly != nil {
+			lc.NameOnly = opt.NameOnly
+		}
+	}
+
+	return lc
+}
diff --git a/vendor/github.com/mongodb/mongo-go-driver/mongo/options/listdatabasesoptions.go b/vendor/github.com/mongodb/mongo-go-driver/mongo/options/listdatabasesoptions.go
new file mode 100644
index 0000000..5efb6e8
--- /dev/null
+++ b/vendor/github.com/mongodb/mongo-go-driver/mongo/options/listdatabasesoptions.go
@@ -0,0 +1,39 @@
+// Copyright (C) MongoDB, Inc. 2017-present.
+//
+// Licensed under the Apache License, Version 2.0 (the "License"); you may
+// not use this file except in compliance with the License. You may obtain
+// a copy of the License at http://www.apache.org/licenses/LICENSE-2.0
+
+package options
+
+// ListDatabasesOptions represents all possible options for a listDatabases command.
+type ListDatabasesOptions struct {
+	NameOnly *bool // If true, only the database names will be returned.
+}
+
+// ListDatabases creates a new *ListDatabasesOptions
+func ListDatabases() *ListDatabasesOptions {
+	return &ListDatabasesOptions{}
+}
+
+// SetNameOnly specifies whether to return only the database names.
+func (ld *ListDatabasesOptions) SetNameOnly(b bool) *ListDatabasesOptions {
+	ld.NameOnly = &b
+	return ld
+}
+
+// MergeListDatabasesOptions combines the given *ListDatabasesOptions into a single *ListDatabasesOptions in a last one
+// wins fashion.
+func MergeListDatabasesOptions(opts ...*ListDatabasesOptions) *ListDatabasesOptions {
+	ld := ListDatabases()
+	for _, opt := range opts {
+		if opts == nil {
+			continue
+		}
+		if opt.NameOnly != nil {
+			ld.NameOnly = opt.NameOnly
+		}
+	}
+
+	return ld
+}
diff --git a/vendor/github.com/mongodb/mongo-go-driver/mongo/options/mongooptions.go b/vendor/github.com/mongodb/mongo-go-driver/mongo/options/mongooptions.go
new file mode 100644
index 0000000..22f383b
--- /dev/null
+++ b/vendor/github.com/mongodb/mongo-go-driver/mongo/options/mongooptions.go
@@ -0,0 +1,163 @@
+// Copyright (C) MongoDB, Inc. 2017-present.
+//
+// Licensed under the Apache License, Version 2.0 (the "License"); you may
+// not use this file except in compliance with the License. You may obtain
+// a copy of the License at http://www.apache.org/licenses/LICENSE-2.0
+
+package options
+
+import (
+	"fmt"
+	"reflect"
+
+	"github.com/mongodb/mongo-go-driver/bson"
+	"github.com/mongodb/mongo-go-driver/bson/bsoncodec"
+	"github.com/mongodb/mongo-go-driver/x/bsonx"
+)
+
+// Collation allows users to specify language-specific rules for string comparison, such as
+// rules for lettercase and accent marks.
+type Collation struct {
+	Locale          string `bson:",omitempty"` // The locale
+	CaseLevel       bool   `bson:",omitempty"` // The case level
+	CaseFirst       string `bson:",omitempty"` // The case ordering
+	Strength        int    `bson:",omitempty"` // The number of comparision levels to use
+	NumericOrdering bool   `bson:",omitempty"` // Whether to order numbers based on numerical order and not collation order
+	Alternate       string `bson:",omitempty"` // Whether spaces and punctuation are considered base characters
+	MaxVariable     string `bson:",omitempty"` // Which characters are affected by alternate: "shifted"
+	Normalization   bool   `bson:",omitempty"` // Causes text to be normalized into Unicode NFD
+	Backwards       bool   `bson:",omitempty"` // Causes secondary differences to be considered in reverse order, as it is done in the French language
+}
+
+// ToDocument converts the Collation to a *bsonx.Document
+func (co *Collation) ToDocument() bsonx.Doc {
+	doc := bsonx.Doc{}
+	if co.Locale != "" {
+		doc = append(doc, bsonx.Elem{"locale", bsonx.String(co.Locale)})
+	}
+	if co.CaseLevel {
+		doc = append(doc, bsonx.Elem{"caseLevel", bsonx.Boolean(true)})
+	}
+	if co.CaseFirst != "" {
+		doc = append(doc, bsonx.Elem{"caseFirst", bsonx.String(co.CaseFirst)})
+	}
+	if co.Strength != 0 {
+		doc = append(doc, bsonx.Elem{"strength", bsonx.Int32(int32(co.Strength))})
+	}
+	if co.NumericOrdering {
+		doc = append(doc, bsonx.Elem{"numericOrdering", bsonx.Boolean(true)})
+	}
+	if co.Alternate != "" {
+		doc = append(doc, bsonx.Elem{"alternate", bsonx.String(co.Alternate)})
+	}
+	if co.MaxVariable != "" {
+		doc = append(doc, bsonx.Elem{"maxVariable", bsonx.String(co.MaxVariable)})
+	}
+	if co.Normalization {
+		doc = append(doc, bsonx.Elem{"normalization", bsonx.Boolean(co.Normalization)})
+	}
+	if co.Backwards {
+		doc = append(doc, bsonx.Elem{"backwards", bsonx.Boolean(true)})
+	}
+	return doc
+}
+
+// CursorType specifies whether a cursor should close when the last data is retrieved. See
+// NonTailable, Tailable, and TailableAwait.
+type CursorType int8
+
+const (
+	// NonTailable specifies that a cursor should close after retrieving the last data.
+	NonTailable CursorType = iota
+	// Tailable specifies that a cursor should not close when the last data is retrieved and can be resumed later.
+	Tailable
+	// TailableAwait specifies that a cursor should not close when the last data is retrieved and
+	// that it should block for a certain amount of time for new data before returning no data.
+	TailableAwait
+)
+
+// ReturnDocument specifies whether a findAndUpdate operation should return the document as it was
+// before the update or as it is after the update.
+type ReturnDocument int8
+
+const (
+	// Before specifies that findAndUpdate should return the document as it was before the update.
+	Before ReturnDocument = iota
+	// After specifies that findAndUpdate should return the document as it is after the update.
+	After
+)
+
+// FullDocument specifies whether a change stream should include a copy of the entire document that was changed from
+// some time after the change occurred.
+type FullDocument string
+
+const (
+	// Default does not include a document copy
+	Default FullDocument = "default"
+	// UpdateLookup includes a delta describing the changes to the document and a copy of the entire document that
+	// was changed
+	UpdateLookup FullDocument = "updateLookup"
+)
+
+// ArrayFilters is used to hold filters for the array filters CRUD option. If a registry is nil, bson.DefaultRegistry
+// will be used when converting the filter interfaces to BSON.
+type ArrayFilters struct {
+	Registry *bsoncodec.Registry // The registry to use for converting filters. Defaults to bson.DefaultRegistry.
+	Filters  []interface{}       // The filters to apply
+}
+
+// ToArray builds a bsonx.Arr from the provided ArrayFilters.
+func (af *ArrayFilters) ToArray() (bsonx.Arr, error) {
+	docs := make([]bsonx.Doc, 0, len(af.Filters))
+	for _, f := range af.Filters {
+		d, err := transformDocument(af.Registry, f)
+		if err != nil {
+			return nil, err
+		}
+		docs = append(docs, d)
+	}
+
+	arr := bsonx.Arr{}
+	for _, doc := range docs {
+		arr = append(arr, bsonx.Document(doc))
+	}
+
+	return arr, nil
+}
+
+// MarshalError is returned when attempting to transform a value into a document
+// results in an error.
+type MarshalError struct {
+	Value interface{}
+	Err   error
+}
+
+// Error implements the error interface.
+func (me MarshalError) Error() string {
+	return fmt.Sprintf("cannot transform type %s to a *bsonx.Document", reflect.TypeOf(me.Value))
+}
+
+var defaultRegistry = bson.DefaultRegistry
+
+func transformDocument(registry *bsoncodec.Registry, val interface{}) (bsonx.Doc, error) {
+	if val == nil {
+		return bsonx.Doc{}, nil
+	}
+	reg := defaultRegistry
+	if registry != nil {
+		reg = registry
+	}
+
+	if bs, ok := val.([]byte); ok {
+		// Slight optimization so we'll just use MarshalBSON and not go through the codec machinery.
+		val = bson.Raw(bs)
+	}
+
+	// TODO(skriptble): Use a pool of these instead.
+	buf := make([]byte, 0, 256)
+	b, err := bson.MarshalAppendWithRegistry(reg, buf, val)
+	if err != nil {
+		return nil, MarshalError{Value: val, Err: err}
+	}
+	return bsonx.ReadDoc(b)
+}
diff --git a/vendor/github.com/mongodb/mongo-go-driver/mongo/options/replaceoptions.go b/vendor/github.com/mongodb/mongo-go-driver/mongo/options/replaceoptions.go
new file mode 100644
index 0000000..7a8c2ba
--- /dev/null
+++ b/vendor/github.com/mongodb/mongo-go-driver/mongo/options/replaceoptions.go
@@ -0,0 +1,60 @@
+// Copyright (C) MongoDB, Inc. 2017-present.
+//
+// Licensed under the Apache License, Version 2.0 (the "License"); you may
+// not use this file except in compliance with the License. You may obtain
+// a copy of the License at http://www.apache.org/licenses/LICENSE-2.0
+
+package options
+
+// ReplaceOptions represents all possible options to the replaceOne() function
+type ReplaceOptions struct {
+	BypassDocumentValidation *bool      // If true, allows the write to opt-out of document level validation
+	Collation                *Collation // Specifies a collation
+	Upsert                   *bool      // When true, creates a new document if no document matches the query
+}
+
+// Replace returns a pointer to a new ReplaceOptions
+func Replace() *ReplaceOptions {
+	return &ReplaceOptions{}
+}
+
+// SetBypassDocumentValidation allows the write to opt-out of document level validation.
+// Valid for server versions >= 3.2. For servers < 3.2, this option is ignored.
+func (ro *ReplaceOptions) SetBypassDocumentValidation(b bool) *ReplaceOptions {
+	ro.BypassDocumentValidation = &b
+	return ro
+}
+
+// SetCollation specifies a collation.
+// Valid for servers >= 3.4
+func (ro *ReplaceOptions) SetCollation(c *Collation) *ReplaceOptions {
+	ro.Collation = c
+	return ro
+}
+
+// SetUpsert allows the creation of a new document if not document matches the query
+func (ro *ReplaceOptions) SetUpsert(b bool) *ReplaceOptions {
+	ro.Upsert = &b
+	return ro
+}
+
+// MergeReplaceOptions combines the argued ReplaceOptions into a single ReplaceOptions in a last-one-wins fashion
+func MergeReplaceOptions(opts ...*ReplaceOptions) *ReplaceOptions {
+	rOpts := Replace()
+	for _, ro := range opts {
+		if ro == nil {
+			continue
+		}
+		if ro.BypassDocumentValidation != nil {
+			rOpts.BypassDocumentValidation = ro.BypassDocumentValidation
+		}
+		if ro.Collation != nil {
+			rOpts.Collation = ro.Collation
+		}
+		if ro.Upsert != nil {
+			rOpts.Upsert = ro.Upsert
+		}
+	}
+
+	return rOpts
+}
diff --git a/vendor/github.com/mongodb/mongo-go-driver/mongo/options/runcmdoptions.go b/vendor/github.com/mongodb/mongo-go-driver/mongo/options/runcmdoptions.go
new file mode 100644
index 0000000..c7c696d
--- /dev/null
+++ b/vendor/github.com/mongodb/mongo-go-driver/mongo/options/runcmdoptions.go
@@ -0,0 +1,40 @@
+// Copyright (C) MongoDB, Inc. 2017-present.
+//
+// Licensed under the Apache License, Version 2.0 (the "License"); you may
+// not use this file except in compliance with the License. You may obtain
+// a copy of the License at http://www.apache.org/licenses/LICENSE-2.0
+
+package options
+
+import "github.com/mongodb/mongo-go-driver/mongo/readpref"
+
+// RunCmdOptions represents all possible options for a runCommand operation.
+type RunCmdOptions struct {
+	ReadPreference *readpref.ReadPref // The read preference for the operation.
+}
+
+// RunCmd creates a new *RunCmdOptions
+func RunCmd() *RunCmdOptions {
+	return &RunCmdOptions{}
+}
+
+// SetReadPreference sets the read preference for the operation.
+func (rc *RunCmdOptions) SetReadPreference(rp *readpref.ReadPref) *RunCmdOptions {
+	rc.ReadPreference = rp
+	return rc
+}
+
+// MergeRunCmdOptions combines the given *RunCmdOptions into one *RunCmdOptions in a last one wins fashion.
+func MergeRunCmdOptions(opts ...*RunCmdOptions) *RunCmdOptions {
+	rc := RunCmd()
+	for _, opt := range opts {
+		if opt == nil {
+			continue
+		}
+		if opt.ReadPreference != nil {
+			rc.ReadPreference = opt.ReadPreference
+		}
+	}
+
+	return rc
+}
diff --git a/vendor/github.com/mongodb/mongo-go-driver/mongo/options/sessionoptions.go b/vendor/github.com/mongodb/mongo-go-driver/mongo/options/sessionoptions.go
new file mode 100644
index 0000000..ffe45e6
--- /dev/null
+++ b/vendor/github.com/mongodb/mongo-go-driver/mongo/options/sessionoptions.go
@@ -0,0 +1,79 @@
+// Copyright (C) MongoDB, Inc. 2017-present.
+//
+// Licensed under the Apache License, Version 2.0 (the "License"); you may
+// not use this file except in compliance with the License. You may obtain
+// a copy of the License at http://www.apache.org/licenses/LICENSE-2.0
+
+package options
+
+import (
+	"github.com/mongodb/mongo-go-driver/mongo/readconcern"
+	"github.com/mongodb/mongo-go-driver/mongo/readpref"
+	"github.com/mongodb/mongo-go-driver/mongo/writeconcern"
+)
+
+// DefaultCausalConsistency is the default value for the CausalConsistency option.
+var DefaultCausalConsistency = true
+
+// SessionOptions represents all possible options for creating a new session.
+type SessionOptions struct {
+	CausalConsistency     *bool                      // Specifies if reads should be causally consistent. Defaults to true.
+	DefaultReadConcern    *readconcern.ReadConcern   // The default read concern for transactions started in the session.
+	DefaultReadPreference *readpref.ReadPref         // The default read preference for transactions started in the session.
+	DefaultWriteConcern   *writeconcern.WriteConcern // The default write concern for transactions started in the session.
+}
+
+// Session creates a new *SessionOptions
+func Session() *SessionOptions {
+	return &SessionOptions{
+		CausalConsistency: &DefaultCausalConsistency,
+	}
+}
+
+// SetCausalConsistency specifies if a session should be causally consistent. Defaults to true.
+func (s *SessionOptions) SetCausalConsistency(b bool) *SessionOptions {
+	s.CausalConsistency = &b
+	return s
+}
+
+// SetDefaultReadConcern sets the default read concern for transactions started in a session.
+func (s *SessionOptions) SetDefaultReadConcern(rc *readconcern.ReadConcern) *SessionOptions {
+	s.DefaultReadConcern = rc
+	return s
+}
+
+// SetDefaultReadPreference sets the default read preference for transactions started in a session.
+func (s *SessionOptions) SetDefaultReadPreference(rp *readpref.ReadPref) *SessionOptions {
+	s.DefaultReadPreference = rp
+	return s
+}
+
+// SetDefaultWriteConcern sets the default write concern for transactions started in a session.
+func (s *SessionOptions) SetDefaultWriteConcern(wc *writeconcern.WriteConcern) *SessionOptions {
+	s.DefaultWriteConcern = wc
+	return s
+}
+
+// MergeSessionOptions combines the given *SessionOptions into a single *SessionOptions in a last one wins fashion.
+func MergeSessionOptions(opts ...*SessionOptions) *SessionOptions {
+	s := Session()
+	for _, opt := range opts {
+		if opt == nil {
+			continue
+		}
+		if opt.CausalConsistency != nil {
+			s.CausalConsistency = opt.CausalConsistency
+		}
+		if opt.DefaultReadConcern != nil {
+			s.DefaultReadConcern = opt.DefaultReadConcern
+		}
+		if opt.DefaultReadPreference != nil {
+			s.DefaultReadPreference = opt.DefaultReadPreference
+		}
+		if opt.DefaultWriteConcern != nil {
+			s.DefaultWriteConcern = opt.DefaultWriteConcern
+		}
+	}
+
+	return s
+}
diff --git a/vendor/github.com/mongodb/mongo-go-driver/mongo/options/transactionoptions.go b/vendor/github.com/mongodb/mongo-go-driver/mongo/options/transactionoptions.go
new file mode 100644
index 0000000..5aec1b9
--- /dev/null
+++ b/vendor/github.com/mongodb/mongo-go-driver/mongo/options/transactionoptions.go
@@ -0,0 +1,65 @@
+// Copyright (C) MongoDB, Inc. 2017-present.
+//
+// Licensed under the Apache License, Version 2.0 (the "License"); you may
+// not use this file except in compliance with the License. You may obtain
+// a copy of the License at http://www.apache.org/licenses/LICENSE-2.0
+
+package options
+
+import (
+	"github.com/mongodb/mongo-go-driver/mongo/readconcern"
+	"github.com/mongodb/mongo-go-driver/mongo/readpref"
+	"github.com/mongodb/mongo-go-driver/mongo/writeconcern"
+)
+
+// TransactionOptions represents all possible options for starting a transaction.
+type TransactionOptions struct {
+	ReadConcern    *readconcern.ReadConcern   // The read concern for the transaction. Defaults to the session's read concern.
+	ReadPreference *readpref.ReadPref         // The read preference for the transaction. Defaults to the session's read preference.
+	WriteConcern   *writeconcern.WriteConcern // The write concern for the transaction. Defaults to the session's write concern.
+}
+
+// Transaction creates a new *TransactionOptions
+func Transaction() *TransactionOptions {
+	return &TransactionOptions{}
+}
+
+// SetReadConcern sets the read concern for the transaction.
+func (t *TransactionOptions) SetReadConcern(rc *readconcern.ReadConcern) *TransactionOptions {
+	t.ReadConcern = rc
+	return t
+}
+
+// SetReadPreference sets the read preference for the transaction.
+func (t *TransactionOptions) SetReadPreference(rp *readpref.ReadPref) *TransactionOptions {
+	t.ReadPreference = rp
+	return t
+}
+
+// SetWriteConcern sets the write concern for the transaction.
+func (t *TransactionOptions) SetWriteConcern(wc *writeconcern.WriteConcern) *TransactionOptions {
+	t.WriteConcern = wc
+	return t
+}
+
+// MergeTransactionOptions combines the given *TransactionOptions into a single *TransactionOptions in a last one wins
+// fashion.
+func MergeTransactionOptions(opts ...*TransactionOptions) *TransactionOptions {
+	t := Transaction()
+	for _, opt := range opts {
+		if opt == nil {
+			continue
+		}
+		if opt.ReadConcern != nil {
+			t.ReadConcern = opt.ReadConcern
+		}
+		if opt.ReadPreference != nil {
+			t.ReadPreference = opt.ReadPreference
+		}
+		if opt.WriteConcern != nil {
+			t.WriteConcern = opt.WriteConcern
+		}
+	}
+
+	return t
+}
diff --git a/vendor/github.com/mongodb/mongo-go-driver/mongo/options/updateoptions.go b/vendor/github.com/mongodb/mongo-go-driver/mongo/options/updateoptions.go
new file mode 100644
index 0000000..468ccda
--- /dev/null
+++ b/vendor/github.com/mongodb/mongo-go-driver/mongo/options/updateoptions.go
@@ -0,0 +1,71 @@
+// Copyright (C) MongoDB, Inc. 2017-present.
+//
+// Licensed under the Apache License, Version 2.0 (the "License"); you may
+// not use this file except in compliance with the License. You may obtain
+// a copy of the License at http://www.apache.org/licenses/LICENSE-2.0
+
+package options
+
+// UpdateOptions represents all possible options to the updateOne() and updateMany() functions
+type UpdateOptions struct {
+	ArrayFilters             *ArrayFilters // A set of filters specifying to which array elements an update should apply
+	BypassDocumentValidation *bool         // If true, allows the write to opt-out of document level validation
+	Collation                *Collation    // Specifies a collation
+	Upsert                   *bool         // When true, creates a new document if no document matches the query
+}
+
+// Update returns a pointer to a new UpdateOptions
+func Update() *UpdateOptions {
+	return &UpdateOptions{}
+}
+
+// SetArrayFilters specifies a set of filters specifying to which array elements an update should apply
+// Valid for server versions >= 3.6.
+func (uo *UpdateOptions) SetArrayFilters(af ArrayFilters) *UpdateOptions {
+	uo.ArrayFilters = &af
+	return uo
+}
+
+// SetBypassDocumentValidation allows the write to opt-out of document level validation.
+// Valid for server versions >= 3.2. For servers < 3.2, this option is ignored.
+func (uo *UpdateOptions) SetBypassDocumentValidation(b bool) *UpdateOptions {
+	uo.BypassDocumentValidation = &b
+	return uo
+}
+
+// SetCollation specifies a collation.
+// Valid for server versions >= 3.4.
+func (uo *UpdateOptions) SetCollation(c *Collation) *UpdateOptions {
+	uo.Collation = c
+	return uo
+}
+
+// SetUpsert allows the creation of a new document if not document matches the query
+func (uo *UpdateOptions) SetUpsert(b bool) *UpdateOptions {
+	uo.Upsert = &b
+	return uo
+}
+
+// MergeUpdateOptions combines the argued UpdateOptions into a single UpdateOptions in a last-one-wins fashion
+func MergeUpdateOptions(opts ...*UpdateOptions) *UpdateOptions {
+	uOpts := Update()
+	for _, uo := range opts {
+		if uo == nil {
+			continue
+		}
+		if uo.ArrayFilters != nil {
+			uOpts.ArrayFilters = uo.ArrayFilters
+		}
+		if uo.BypassDocumentValidation != nil {
+			uOpts.BypassDocumentValidation = uo.BypassDocumentValidation
+		}
+		if uo.Collation != nil {
+			uOpts.Collation = uo.Collation
+		}
+		if uo.Upsert != nil {
+			uOpts.Upsert = uo.Upsert
+		}
+	}
+
+	return uOpts
+}
diff --git a/vendor/github.com/mongodb/mongo-go-driver/mongo/readconcern/readconcern.go b/vendor/github.com/mongodb/mongo-go-driver/mongo/readconcern/readconcern.go
new file mode 100644
index 0000000..c185fff
--- /dev/null
+++ b/vendor/github.com/mongodb/mongo-go-driver/mongo/readconcern/readconcern.go
@@ -0,0 +1,77 @@
+// Copyright (C) MongoDB, Inc. 2017-present.
+//
+// Licensed under the Apache License, Version 2.0 (the "License"); you may
+// not use this file except in compliance with the License. You may obtain
+// a copy of the License at http://www.apache.org/licenses/LICENSE-2.0
+
+package readconcern
+
+import (
+	"github.com/mongodb/mongo-go-driver/bson/bsontype"
+	"github.com/mongodb/mongo-go-driver/x/bsonx/bsoncore"
+)
+
+// ReadConcern for replica sets and replica set shards determines which data to return from a query.
+type ReadConcern struct {
+	level string
+}
+
+// Option is an option to provide when creating a ReadConcern.
+type Option func(concern *ReadConcern)
+
+// Level creates an option that sets the level of a ReadConcern.
+func Level(level string) Option {
+	return func(concern *ReadConcern) {
+		concern.level = level
+	}
+}
+
+// Local specifies that the query should return the instance’s most recent data.
+func Local() *ReadConcern {
+	return New(Level("local"))
+}
+
+// Majority specifies that the query should return the instance’s most recent data acknowledged as
+// having been written to a majority of members in the replica set.
+func Majority() *ReadConcern {
+	return New(Level("majority"))
+}
+
+// Linearizable specifies that the query should return data that reflects all successful writes
+// issued with a write concern of "majority" and acknowledged prior to the start of the read operation.
+func Linearizable() *ReadConcern {
+	return New(Level("linearizable"))
+}
+
+// Available specifies that the query should return data from the instance with no guarantee
+// that the data has been written to a majority of the replica set members (i.e. may be rolled back).
+func Available() *ReadConcern {
+	return New(Level("available"))
+}
+
+// Snapshot is only available for operations within multi-document transactions.
+func Snapshot() *ReadConcern {
+	return New(Level("snapshot"))
+}
+
+// New constructs a new read concern from the given string.
+func New(options ...Option) *ReadConcern {
+	concern := &ReadConcern{}
+
+	for _, option := range options {
+		option(concern)
+	}
+
+	return concern
+}
+
+// MarshalBSONValue implements the bson.ValueMarshaler interface.
+func (rc *ReadConcern) MarshalBSONValue() (bsontype.Type, []byte, error) {
+	var elems []byte
+
+	if len(rc.level) > 0 {
+		elems = bsoncore.AppendStringElement(elems, "level", rc.level)
+	}
+
+	return bsontype.EmbeddedDocument, bsoncore.BuildDocument(nil, elems), nil
+}
diff --git a/vendor/github.com/mongodb/mongo-go-driver/mongo/readpref/mode.go b/vendor/github.com/mongodb/mongo-go-driver/mongo/readpref/mode.go
new file mode 100644
index 0000000..e7030c6
--- /dev/null
+++ b/vendor/github.com/mongodb/mongo-go-driver/mongo/readpref/mode.go
@@ -0,0 +1,56 @@
+// Copyright (C) MongoDB, Inc. 2017-present.
+//
+// Licensed under the Apache License, Version 2.0 (the "License"); you may
+// not use this file except in compliance with the License. You may obtain
+// a copy of the License at http://www.apache.org/licenses/LICENSE-2.0
+
+package readpref
+
+import (
+	"fmt"
+	"strings"
+)
+
+// Mode indicates the user's preference on reads.
+type Mode uint8
+
+// Mode constants
+const (
+	_ Mode = iota
+	// PrimaryMode indicates that only a primary is
+	// considered for reading. This is the default
+	// mode.
+	PrimaryMode
+	// PrimaryPreferredMode indicates that if a primary
+	// is available, use it; otherwise, eligible
+	// secondaries will be considered.
+	PrimaryPreferredMode
+	// SecondaryMode indicates that only secondaries
+	// should be considered.
+	SecondaryMode
+	// SecondaryPreferredMode indicates that only secondaries
+	// should be considered when one is available. If none
+	// are available, then a primary will be considered.
+	SecondaryPreferredMode
+	// NearestMode indicates that all primaries and secondaries
+	// will be considered.
+	NearestMode
+)
+
+// ModeFromString returns a mode corresponding to
+// mode.
+func ModeFromString(mode string) (Mode, error) {
+	switch strings.ToLower(mode) {
+	case "primary":
+		return PrimaryMode, nil
+	case "primarypreferred":
+		return PrimaryPreferredMode, nil
+	case "secondary":
+		return SecondaryMode, nil
+	case "secondarypreferred":
+		return SecondaryPreferredMode, nil
+	case "nearest":
+		return NearestMode, nil
+	}
+	return Mode(0), fmt.Errorf("unknown read preference %v", mode)
+}
diff --git a/vendor/github.com/mongodb/mongo-go-driver/mongo/readpref/options.go b/vendor/github.com/mongodb/mongo-go-driver/mongo/readpref/options.go
new file mode 100644
index 0000000..a81cf3e
--- /dev/null
+++ b/vendor/github.com/mongodb/mongo-go-driver/mongo/readpref/options.go
@@ -0,0 +1,60 @@
+// Copyright (C) MongoDB, Inc. 2017-present.
+//
+// Licensed under the Apache License, Version 2.0 (the "License"); you may
+// not use this file except in compliance with the License. You may obtain
+// a copy of the License at http://www.apache.org/licenses/LICENSE-2.0
+
+package readpref
+
+import (
+	"errors"
+	"time"
+
+	"github.com/mongodb/mongo-go-driver/tag"
+)
+
+// ErrInvalidTagSet indicates that an invalid set of tags was specified.
+var ErrInvalidTagSet = errors.New("an even number of tags must be specified")
+
+// Option configures a read preference
+type Option func(*ReadPref) error
+
+// WithMaxStaleness sets the maximum staleness a
+// server is allowed.
+func WithMaxStaleness(ms time.Duration) Option {
+	return func(rp *ReadPref) error {
+		rp.maxStaleness = ms
+		rp.maxStalenessSet = true
+		return nil
+	}
+}
+
+// WithTags sets a single tag set used to match
+// a server. The last call to WithTags or WithTagSets
+// overrides all previous calls to either method.
+func WithTags(tags ...string) Option {
+	return func(rp *ReadPref) error {
+		length := len(tags)
+		if length < 2 || length%2 != 0 {
+			return ErrInvalidTagSet
+		}
+
+		tagset := make(tag.Set, 0, length/2)
+
+		for i := 1; i < length; i += 2 {
+			tagset = append(tagset, tag.Tag{Name: tags[i-1], Value: tags[i]})
+		}
+
+		return WithTagSets(tagset)(rp)
+	}
+}
+
+// WithTagSets sets the tag sets used to match
+// a server. The last call to WithTags or WithTagSets
+// overrides all previous calls to either method.
+func WithTagSets(tagSets ...tag.Set) Option {
+	return func(rp *ReadPref) error {
+		rp.tagSets = tagSets
+		return nil
+	}
+}
diff --git a/vendor/github.com/mongodb/mongo-go-driver/mongo/readpref/readpref.go b/vendor/github.com/mongodb/mongo-go-driver/mongo/readpref/readpref.go
new file mode 100644
index 0000000..0d624ff
--- /dev/null
+++ b/vendor/github.com/mongodb/mongo-go-driver/mongo/readpref/readpref.go
@@ -0,0 +1,99 @@
+// Copyright (C) MongoDB, Inc. 2017-present.
+//
+// Licensed under the Apache License, Version 2.0 (the "License"); you may
+// not use this file except in compliance with the License. You may obtain
+// a copy of the License at http://www.apache.org/licenses/LICENSE-2.0
+
+package readpref
+
+import (
+	"errors"
+	"time"
+
+	"github.com/mongodb/mongo-go-driver/tag"
+)
+
+var (
+	errInvalidReadPreference = errors.New("can not specify tags or max staleness on primary")
+)
+
+var primary = ReadPref{mode: PrimaryMode}
+
+// Primary constructs a read preference with a PrimaryMode.
+func Primary() *ReadPref {
+	return &primary
+}
+
+// PrimaryPreferred constructs a read preference with a PrimaryPreferredMode.
+func PrimaryPreferred(opts ...Option) *ReadPref {
+	// New only returns an error with a mode of Primary
+	rp, _ := New(PrimaryPreferredMode, opts...)
+	return rp
+}
+
+// SecondaryPreferred constructs a read preference with a SecondaryPreferredMode.
+func SecondaryPreferred(opts ...Option) *ReadPref {
+	// New only returns an error with a mode of Primary
+	rp, _ := New(SecondaryPreferredMode, opts...)
+	return rp
+}
+
+// Secondary constructs a read preference with a SecondaryMode.
+func Secondary(opts ...Option) *ReadPref {
+	// New only returns an error with a mode of Primary
+	rp, _ := New(SecondaryMode, opts...)
+	return rp
+}
+
+// Nearest constructs a read preference with a NearestMode.
+func Nearest(opts ...Option) *ReadPref {
+	// New only returns an error with a mode of Primary
+	rp, _ := New(NearestMode, opts...)
+	return rp
+}
+
+// New creates a new ReadPref.
+func New(mode Mode, opts ...Option) (*ReadPref, error) {
+	rp := &ReadPref{
+		mode: mode,
+	}
+
+	if mode == PrimaryMode && len(opts) != 0 {
+		return nil, errInvalidReadPreference
+	}
+
+	for _, opt := range opts {
+		err := opt(rp)
+		if err != nil {
+			return nil, err
+		}
+	}
+
+	return rp, nil
+}
+
+// ReadPref determines which servers are considered suitable for read operations.
+type ReadPref struct {
+	maxStaleness    time.Duration
+	maxStalenessSet bool
+	mode            Mode
+	tagSets         []tag.Set
+}
+
+// MaxStaleness is the maximum amount of time to allow
+// a server to be considered eligible for selection. The
+// second return value indicates if this value has been set.
+func (r *ReadPref) MaxStaleness() (time.Duration, bool) {
+	return r.maxStaleness, r.maxStalenessSet
+}
+
+// Mode indicates the mode of the read preference.
+func (r *ReadPref) Mode() Mode {
+	return r.mode
+}
+
+// TagSets are multiple tag sets indicating
+// which servers should be considered.
+func (r *ReadPref) TagSets() []tag.Set {
+	return r.tagSets
+}
diff --git a/vendor/github.com/mongodb/mongo-go-driver/mongo/results.go b/vendor/github.com/mongodb/mongo-go-driver/mongo/results.go
new file mode 100644
index 0000000..b4bcd02
--- /dev/null
+++ b/vendor/github.com/mongodb/mongo-go-driver/mongo/results.go
@@ -0,0 +1,139 @@
+// Copyright (C) MongoDB, Inc. 2017-present.
+//
+// Licensed under the Apache License, Version 2.0 (the "License"); you may
+// not use this file except in compliance with the License. You may obtain
+// a copy of the License at http://www.apache.org/licenses/LICENSE-2.0
+
+package mongo
+
+import (
+	"fmt"
+
+	"github.com/mongodb/mongo-go-driver/bson"
+	"github.com/mongodb/mongo-go-driver/x/network/result"
+)
+
+// BulkWriteResult holds the result of a bulk write operation.
+type BulkWriteResult struct {
+	InsertedCount int64
+	MatchedCount  int64
+	ModifiedCount int64
+	DeletedCount  int64
+	UpsertedCount int64
+	UpsertedIDs   map[int64]interface{}
+}
+
+// InsertOneResult is a result of an InsertOne operation.
+//
+// InsertedID will be a Go type that corresponds to a BSON type.
+type InsertOneResult struct {
+	// The identifier that was inserted.
+	InsertedID interface{}
+}
+
+// InsertManyResult is a result of an InsertMany operation.
+type InsertManyResult struct {
+	// Maps the indexes of inserted documents to their _id fields.
+	InsertedIDs []interface{}
+}
+
+// DeleteResult is a result of an DeleteOne operation.
+type DeleteResult struct {
+	// The number of documents that were deleted.
+	DeletedCount int64 `bson:"n"`
+}
+
+// ListDatabasesResult is a result of a ListDatabases operation. Each specification
+// is a description of the datbases on the server.
+type ListDatabasesResult struct {
+	Databases []DatabaseSpecification
+	TotalSize int64
+}
+
+func (ldr ListDatabasesResult) fromResult(res result.ListDatabases) ListDatabasesResult {
+	ldr.Databases = make([]DatabaseSpecification, 0, len(res.Databases))
+	for _, spec := range res.Databases {
+		ldr.Databases = append(
+			ldr.Databases,
+			DatabaseSpecification{Name: spec.Name, SizeOnDisk: spec.SizeOnDisk, Empty: spec.Empty},
+		)
+	}
+	ldr.TotalSize = res.TotalSize
+	return ldr
+}
+
+// DatabaseSpecification is the information for a single database returned
+// from a ListDatabases operation.
+type DatabaseSpecification struct {
+	Name       string
+	SizeOnDisk int64
+	Empty      bool
+}
+
+// UpdateResult is a result of an update operation.
+//
+// UpsertedID will be a Go type that corresponds to a BSON type.
+type UpdateResult struct {
+	// The number of documents that matched the filter.
+	MatchedCount int64
+	// The number of documents that were modified.
+	ModifiedCount int64
+	// The number of documents that were upserted.
+	UpsertedCount int64
+	// The identifier of the inserted document if an upsert took place.
+	UpsertedID interface{}
+}
+
+// UnmarshalBSON implements the bson.Unmarshaler interface.
+func (result *UpdateResult) UnmarshalBSON(b []byte) error {
+	elems, err := bson.Raw(b).Elements()
+	if err != nil {
+		return err
+	}
+
+	for _, elem := range elems {
+		switch elem.Key() {
+		case "n":
+			switch elem.Value().Type {
+			case bson.TypeInt32:
+				result.MatchedCount = int64(elem.Value().Int32())
+			case bson.TypeInt64:
+				result.MatchedCount = elem.Value().Int64()
+			default:
+				return fmt.Errorf("Received invalid type for n, should be Int32 or Int64, received %s", elem.Value().Type)
+			}
+		case "nModified":
+			switch elem.Value().Type {
+			case bson.TypeInt32:
+				result.ModifiedCount = int64(elem.Value().Int32())
+			case bson.TypeInt64:
+				result.ModifiedCount = elem.Value().Int64()
+			default:
+				return fmt.Errorf("Received invalid type for nModified, should be Int32 or Int64, received %s", elem.Value().Type)
+			}
+		case "upserted":
+			switch elem.Value().Type {
+			case bson.TypeArray:
+				e, err := elem.Value().Array().IndexErr(0)
+				if err != nil {
+					break
+				}
+				if e.Value().Type != bson.TypeEmbeddedDocument {
+					break
+				}
+				var d struct {
+					ID interface{} `bson:"_id"`
+				}
+				err = bson.Unmarshal(e.Value().Document(), &d)
+				if err != nil {
+					return err
+				}
+				result.UpsertedID = d.ID
+			default:
+				return fmt.Errorf("Received invalid type for upserted, should be Array, received %s", elem.Value().Type)
+			}
+		}
+	}
+
+	return nil
+}
diff --git a/vendor/github.com/mongodb/mongo-go-driver/mongo/session.go b/vendor/github.com/mongodb/mongo-go-driver/mongo/session.go
new file mode 100644
index 0000000..381714d
--- /dev/null
+++ b/vendor/github.com/mongodb/mongo-go-driver/mongo/session.go
@@ -0,0 +1,181 @@
+// Copyright (C) MongoDB, Inc. 2017-present.
+//
+// Licensed under the Apache License, Version 2.0 (the "License"); you may
+// not use this file except in compliance with the License. You may obtain
+// a copy of the License at http://www.apache.org/licenses/LICENSE-2.0
+
+package mongo
+
+import (
+	"context"
+	"errors"
+
+	"github.com/mongodb/mongo-go-driver/bson"
+	"github.com/mongodb/mongo-go-driver/bson/primitive"
+	"github.com/mongodb/mongo-go-driver/mongo/options"
+	"github.com/mongodb/mongo-go-driver/x/mongo/driver"
+	"github.com/mongodb/mongo-go-driver/x/mongo/driver/session"
+	"github.com/mongodb/mongo-go-driver/x/mongo/driver/topology"
+	"github.com/mongodb/mongo-go-driver/x/network/command"
+	"github.com/mongodb/mongo-go-driver/x/network/description"
+)
+
+// ErrWrongClient is returned when a user attempts to pass in a session created by a different client than
+// the method call is using.
+var ErrWrongClient = errors.New("session was not created by this client")
+
+// SessionContext is a hybrid interface. It combines a context.Context with
+// a mongo.Session. This type can be used as a regular context.Context or
+// Session type. It is not goroutine safe and should not be used in multiple goroutines concurrently.
+type SessionContext interface {
+	context.Context
+	Session
+}
+
+type sessionContext struct {
+	context.Context
+	Session
+}
+
+type sessionKey struct {
+}
+
+// Session is the interface that represents a sequential set of operations executed.
+// Instances of this interface can be used to use transactions against the server
+// and to enable causally consistent behavior for applications.
+type Session interface {
+	EndSession(context.Context)
+	StartTransaction(...*options.TransactionOptions) error
+	AbortTransaction(context.Context) error
+	CommitTransaction(context.Context) error
+	ClusterTime() bson.Raw
+	AdvanceClusterTime(bson.Raw) error
+	OperationTime() *primitive.Timestamp
+	AdvanceOperationTime(*primitive.Timestamp) error
+	session()
+}
+
+// sessionImpl represents a set of sequential operations executed by an application that are related in some way.
+type sessionImpl struct {
+	*session.Client
+	topo                *topology.Topology
+	didCommitAfterStart bool // true if commit was called after start with no other operations
+}
+
+// EndSession ends the session.
+func (s *sessionImpl) EndSession(ctx context.Context) {
+	if s.TransactionInProgress() {
+		// ignore all errors aborting during an end session
+		_ = s.AbortTransaction(ctx)
+	}
+	s.Client.EndSession()
+}
+
+// StartTransaction starts a transaction for this session.
+func (s *sessionImpl) StartTransaction(opts ...*options.TransactionOptions) error {
+	err := s.CheckStartTransaction()
+	if err != nil {
+		return err
+	}
+
+	s.didCommitAfterStart = false
+
+	topts := options.MergeTransactionOptions(opts...)
+	coreOpts := &session.TransactionOptions{
+		ReadConcern:    topts.ReadConcern,
+		ReadPreference: topts.ReadPreference,
+		WriteConcern:   topts.WriteConcern,
+	}
+
+	return s.Client.StartTransaction(coreOpts)
+}
+
+// AbortTransaction aborts the session's transaction, returning any errors and error codes
+func (s *sessionImpl) AbortTransaction(ctx context.Context) error {
+	err := s.CheckAbortTransaction()
+	if err != nil {
+		return err
+	}
+
+	cmd := command.AbortTransaction{
+		Session: s.Client,
+	}
+
+	s.Aborting = true
+	_, err = driver.AbortTransaction(ctx, cmd, s.topo, description.WriteSelector())
+
+	_ = s.Client.AbortTransaction()
+	return err
+}
+
+// CommitTransaction commits the sesson's transaction.
+func (s *sessionImpl) CommitTransaction(ctx context.Context) error {
+	err := s.CheckCommitTransaction()
+	if err != nil {
+		return err
+	}
+
+	// Do not run the commit command if the transaction is in started state
+	if s.TransactionStarting() || s.didCommitAfterStart {
+		s.didCommitAfterStart = true
+		return s.Client.CommitTransaction()
+	}
+
+	if s.Client.TransactionCommitted() {
+		s.RetryingCommit = true
+	}
+
+	cmd := command.CommitTransaction{
+		Session: s.Client,
+	}
+
+	// Hack to ensure that session stays in committed state
+	if s.TransactionCommitted() {
+		s.Committing = true
+		defer func() {
+			s.Committing = false
+		}()
+	}
+	_, err = driver.CommitTransaction(ctx, cmd, s.topo, description.WriteSelector())
+	if err == nil {
+		return s.Client.CommitTransaction()
+	}
+	return err
+}
+
+func (s *sessionImpl) ClusterTime() bson.Raw {
+	return s.Client.ClusterTime
+}
+
+func (s *sessionImpl) AdvanceClusterTime(d bson.Raw) error {
+	return s.Client.AdvanceClusterTime(d)
+}
+
+func (s *sessionImpl) OperationTime() *primitive.Timestamp {
+	return s.Client.OperationTime
+}
+
+func (s *sessionImpl) AdvanceOperationTime(ts *primitive.Timestamp) error {
+	return s.Client.AdvanceOperationTime(ts)
+}
+
+func (*sessionImpl) session() {
+}
+
+// sessionFromContext checks for a sessionImpl in the argued context and returns the session if it
+// exists
+func sessionFromContext(ctx context.Context) *session.Client {
+	s := ctx.Value(sessionKey{})
+	if ses, ok := s.(*sessionImpl); ses != nil && ok {
+		return ses.Client
+	}
+
+	return nil
+}
+
+func contextWithSession(ctx context.Context, sess Session) SessionContext {
+	return &sessionContext{
+		Context: context.WithValue(ctx, sessionKey{}, sess),
+		Session: sess,
+	}
+}
diff --git a/vendor/github.com/mongodb/mongo-go-driver/mongo/single_result.go b/vendor/github.com/mongodb/mongo-go-driver/mongo/single_result.go
new file mode 100644
index 0000000..9a929db
--- /dev/null
+++ b/vendor/github.com/mongodb/mongo-go-driver/mongo/single_result.go
@@ -0,0 +1,93 @@
+// Copyright (C) MongoDB, Inc. 2017-present.
+//
+// Licensed under the Apache License, Version 2.0 (the "License"); you may
+// not use this file except in compliance with the License. You may obtain
+// a copy of the License at http://www.apache.org/licenses/LICENSE-2.0
+
+package mongo
+
+import (
+	"context"
+	"errors"
+
+	"github.com/mongodb/mongo-go-driver/bson"
+	"github.com/mongodb/mongo-go-driver/bson/bsoncodec"
+)
+
+// ErrNoDocuments is returned by Decode when an operation that returns a
+// SingleResult doesn't return any documents.
+var ErrNoDocuments = errors.New("mongo: no documents in result")
+
+// SingleResult represents a single document returned from an operation. If
+// the operation returned an error, the Err method of SingleResult will
+// return that error.
+type SingleResult struct {
+	err error
+	cur *Cursor
+	rdr bson.Raw
+	reg *bsoncodec.Registry
+}
+
+// Decode will attempt to decode the first document into v. If there was an
+// error from the operation that created this SingleResult then the error
+// will be returned. If there were no returned documents, ErrNoDocuments is
+// returned.
+func (sr *SingleResult) Decode(v interface{}) error {
+	if sr.err != nil {
+		return sr.err
+	}
+	if sr.reg == nil {
+		return bson.ErrNilRegistry
+	}
+	switch {
+	case sr.rdr != nil:
+		if v == nil {
+			return nil
+		}
+		return bson.UnmarshalWithRegistry(sr.reg, sr.rdr, v)
+	case sr.cur != nil:
+		defer sr.cur.Close(context.TODO())
+		if !sr.cur.Next(context.TODO()) {
+			if err := sr.cur.Err(); err != nil {
+				return err
+			}
+			return ErrNoDocuments
+		}
+		if v == nil {
+			return nil
+		}
+		return sr.cur.Decode(v)
+	}
+
+	return ErrNoDocuments
+}
+
+// DecodeBytes will return a copy of the document as a bson.Raw. If there was an
+// error from the operation that created this SingleResult then the error
+// will be returned. If there were no returned documents, ErrNoDocuments is
+// returned.
+func (sr *SingleResult) DecodeBytes() (bson.Raw, error) {
+	switch {
+	case sr.err != nil:
+		return nil, sr.err
+	case sr.rdr != nil:
+		return sr.rdr, nil
+	case sr.cur != nil:
+		defer sr.cur.Close(context.TODO())
+		if !sr.cur.Next(context.TODO()) {
+			if err := sr.cur.Err(); err != nil {
+				return nil, err
+			}
+			return nil, ErrNoDocuments
+		}
+		return sr.cur.Current, nil
+	}
+
+	return nil, ErrNoDocuments
+}
+
+// Err will return the error from the operation that created this SingleResult.
+// If there was no error, nil is returned.
+func (sr *SingleResult) Err() error {
+	return sr.err
+}
diff --git a/vendor/github.com/mongodb/mongo-go-driver/mongo/util.go b/vendor/github.com/mongodb/mongo-go-driver/mongo/util.go
new file mode 100644
index 0000000..270fa24
--- /dev/null
+++ b/vendor/github.com/mongodb/mongo-go-driver/mongo/util.go
@@ -0,0 +1,7 @@
+// Copyright (C) MongoDB, Inc. 2017-present.
+//
+// Licensed under the Apache License, Version 2.0 (the "License"); you may
+// not use this file except in compliance with the License. You may obtain
+// a copy of the License at http://www.apache.org/licenses/LICENSE-2.0
+
+package mongo
diff --git a/vendor/github.com/mongodb/mongo-go-driver/mongo/writeconcern/writeconcern.go b/vendor/github.com/mongodb/mongo-go-driver/mongo/writeconcern/writeconcern.go
new file mode 100644
index 0000000..234ba19
--- /dev/null
+++ b/vendor/github.com/mongodb/mongo-go-driver/mongo/writeconcern/writeconcern.go
@@ -0,0 +1,186 @@
+// Copyright (C) MongoDB, Inc. 2017-present.
+//
+// Licensed under the Apache License, Version 2.0 (the "License"); you may
+// not use this file except in compliance with the License. You may obtain
+// a copy of the License at http://www.apache.org/licenses/LICENSE-2.0
+
+package writeconcern
+
+import (
+	"errors"
+	"time"
+
+	"github.com/mongodb/mongo-go-driver/bson"
+	"github.com/mongodb/mongo-go-driver/bson/bsontype"
+	"github.com/mongodb/mongo-go-driver/x/bsonx/bsoncore"
+)
+
+// ErrInconsistent indicates that an inconsistent write concern was specified.
+var ErrInconsistent = errors.New("a write concern cannot have both w=0 and j=true")
+
+// ErrEmptyWriteConcern indicates that a write concern has no fields set.
+var ErrEmptyWriteConcern = errors.New("a write concern must have at least one field set")
+
+// ErrNegativeW indicates that a negative integer `w` field was specified.
+var ErrNegativeW = errors.New("write concern `w` field cannot be a negative number")
+
+// ErrNegativeWTimeout indicates that a negative WTimeout was specified.
+var ErrNegativeWTimeout = errors.New("write concern `wtimeout` field cannot be negative")
+
+// WriteConcern describes the level of acknowledgement requested from MongoDB for write operations
+// to a standalone mongod or to replica sets or to sharded clusters.
+type WriteConcern struct {
+	w        interface{}
+	j        bool
+	wTimeout time.Duration
+}
+
+// Option is an option to provide when creating a ReadConcern.
+type Option func(concern *WriteConcern)
+
+// New constructs a new WriteConcern.
+func New(options ...Option) *WriteConcern {
+	concern := &WriteConcern{}
+
+	for _, option := range options {
+		option(concern)
+	}
+
+	return concern
+}
+
+// W requests acknowledgement that write operations propagate to the specified number of mongod
+// instances.
+func W(w int) Option {
+	return func(concern *WriteConcern) {
+		concern.w = w
+	}
+}
+
+// WMajority requests acknowledgement that write operations propagate to the majority of mongod
+// instances.
+func WMajority() Option {
+	return func(concern *WriteConcern) {
+		concern.w = "majority"
+	}
+}
+
+// WTagSet requests acknowledgement that write operations propagate to the specified mongod
+// instance.
+func WTagSet(tag string) Option {
+	return func(concern *WriteConcern) {
+		concern.w = tag
+	}
+}
+
+// J requests acknowledgement from MongoDB that write operations are written to
+// the journal.
+func J(j bool) Option {
+	return func(concern *WriteConcern) {
+		concern.j = j
+	}
+}
+
+// WTimeout specifies specifies a time limit for the write concern.
+func WTimeout(d time.Duration) Option {
+	return func(concern *WriteConcern) {
+		concern.wTimeout = d
+	}
+}
+
+// MarshalBSONValue implements the bson.ValueMarshaler interface.
+func (wc *WriteConcern) MarshalBSONValue() (bsontype.Type, []byte, error) {
+	if !wc.IsValid() {
+		return bsontype.Type(0), nil, ErrInconsistent
+	}
+
+	var elems []byte
+
+	if wc.w != nil {
+		switch t := wc.w.(type) {
+		case int:
+			if t < 0 {
+				return bsontype.Type(0), nil, ErrNegativeW
+			}
+
+			elems = bsoncore.AppendInt32Element(elems, "w", int32(t))
+		case string:
+			elems = bsoncore.AppendStringElement(elems, "w", string(t))
+		}
+	}
+
+	if wc.j {
+		elems = bsoncore.AppendBooleanElement(elems, "j", wc.j)
+	}
+
+	if wc.wTimeout < 0 {
+		return bsontype.Type(0), nil, ErrNegativeWTimeout
+	}
+
+	if wc.wTimeout != 0 {
+		elems = bsoncore.AppendInt64Element(elems, "wtimeout", int64(wc.wTimeout/time.Millisecond))
+	}
+
+	if len(elems) == 0 {
+		return bsontype.Type(0), nil, ErrEmptyWriteConcern
+	}
+	return bsontype.EmbeddedDocument, bsoncore.BuildDocument(nil, elems), nil
+}
+
+// AcknowledgedValue returns true if a BSON RawValue for a write concern represents an acknowledged write concern.
+// The element's value must be a document representing a write concern.
+func AcknowledgedValue(rawv bson.RawValue) bool {
+	doc, ok := bsoncore.Value{Type: rawv.Type, Data: rawv.Value}.DocumentOK()
+	if !ok {
+		return false
+	}
+
+	val, err := doc.LookupErr("w")
+	if err != nil {
+		// key w not found --> acknowledged
+		return true
+	}
+
+	i32, ok := val.Int32OK()
+	if !ok {
+		return false
+	}
+	return i32 != 0
+}
+
+// Acknowledged indicates whether or not a write with the given write concern will be acknowledged.
+func (wc *WriteConcern) Acknowledged() bool {
+	if wc == nil || wc.j {
+		return true
+	}
+
+	switch v := wc.w.(type) {
+	case int:
+		if v == 0 {
+			return false
+		}
+	}
+
+	return true
+}
+
+// IsValid checks whether the write concern is invalid.
+func (wc *WriteConcern) IsValid() bool {
+	if !wc.j {
+		return true
+	}
+
+	switch v := wc.w.(type) {
+	case int:
+		if v == 0 {
+			return false
+		}
+	}
+
+	return true
+}
+
+// AckWrite returns true if a write concern represents an acknowledged write
+func AckWrite(wc *WriteConcern) bool {
+	return wc == nil || wc.Acknowledged()
+}