You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

265 lines
8.6 KiB

3 years ago
// 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"
"go.mongodb.org/mongo-driver/bson"
"go.mongodb.org/mongo-driver/bson/primitive"
"go.mongodb.org/mongo-driver/x/mongo/driver/operation"
)
// BulkWriteResult is the result type returned by a BulkWrite operation.
type BulkWriteResult struct {
// The number of documents inserted.
InsertedCount int64
// The number of documents matched by filters in update and replace operations.
MatchedCount int64
// The number of documents modified by update and replace operations.
ModifiedCount int64
// The number of documents deleted.
DeletedCount int64
// The number of documents upserted by update and replace operations.
UpsertedCount int64
// A map of operation index to the _id of each upserted document.
UpsertedIDs map[int64]interface{}
}
// InsertOneResult is the result type returned by an InsertOne operation.
type InsertOneResult struct {
// The _id of the inserted document. A value generated by the driver will be of type primitive.ObjectID.
InsertedID interface{}
}
// InsertManyResult is a result type returned by an InsertMany operation.
type InsertManyResult struct {
// The _id values of the inserted documents. Values generated by the driver will be of type primitive.ObjectID.
InsertedIDs []interface{}
}
// DeleteResult is the result type returned by DeleteOne and DeleteMany operations.
type DeleteResult struct {
DeletedCount int64 `bson:"n"` // The number of documents deleted.
}
// ListDatabasesResult is a result of a ListDatabases operation.
type ListDatabasesResult struct {
// A slice containing one DatabaseSpecification for each database matched by the operation's filter.
Databases []DatabaseSpecification
// The total size of the database files of the returned databases in bytes.
// This will be the sum of the SizeOnDisk field for each specification in Databases.
TotalSize int64
}
func newListDatabasesResultFromOperation(res operation.ListDatabasesResult) ListDatabasesResult {
var ldr 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 contains information for a database. This type is returned as part of ListDatabasesResult.
type DatabaseSpecification struct {
Name string // The name of the database.
SizeOnDisk int64 // The total size of the database files on disk in bytes.
Empty bool // Specfies whether or not the database is empty.
}
// UpdateResult is the result type returned from UpdateOne, UpdateMany, and ReplaceOne operations.
type UpdateResult struct {
MatchedCount int64 // The number of documents matched by the filter.
ModifiedCount int64 // The number of documents modified by the operation.
UpsertedCount int64 // The number of documents upserted by the operation.
UpsertedID interface{} // The _id field of the upserted document, or nil if no upsert was done.
}
// 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
}
// IndexSpecification represents an index in a database. This type is returned by the IndexView.ListSpecifications
// function and is also used in the CollectionSpecification type.
type IndexSpecification struct {
// The index name.
Name string
// The namespace for the index. This is a string in the format "databaseName.collectionName".
Namespace string
// The keys specification document for the index.
KeysDocument bson.Raw
// The index version.
Version int32
// The length of time, in seconds, for documents to remain in the collection. The default value is 0, which means
// that documents will remain in the collection until they're explicitly deleted or the collection is dropped.
ExpireAfterSeconds *int32
// If true, the index will only reference documents that contain the fields specified in the index. The default is
// false.
Sparse *bool
// If true, the collection will not accept insertion or update of documents where the index key value matches an
// existing value in the index. The default is false.
Unique *bool
}
var _ bson.Unmarshaler = (*IndexSpecification)(nil)
type unmarshalIndexSpecification struct {
Name string `bson:"name"`
Namespace string `bson:"ns"`
KeysDocument bson.Raw `bson:"key"`
Version int32 `bson:"v"`
ExpireAfterSeconds *int32 `bson:"expireAfterSeconds"`
Sparse *bool `bson:"sparse"`
Unique *bool `bson:"unique"`
}
// UnmarshalBSON implements the bson.Unmarshaler interface.
func (i *IndexSpecification) UnmarshalBSON(data []byte) error {
var temp unmarshalIndexSpecification
if err := bson.Unmarshal(data, &temp); err != nil {
return err
}
i.Name = temp.Name
i.Namespace = temp.Namespace
i.KeysDocument = temp.KeysDocument
i.Version = temp.Version
i.ExpireAfterSeconds = temp.ExpireAfterSeconds
i.Sparse = temp.Sparse
i.Unique = temp.Unique
return nil
}
// CollectionSpecification represents a collection in a database. This type is returned by the
// Database.ListCollectionSpecifications function.
type CollectionSpecification struct {
// The collection name.
Name string
// The type of the collection. This will either be "collection" or "view".
Type string
// Whether or not the collection is readOnly. This will be false for MongoDB versions < 3.4.
ReadOnly bool
// The collection UUID. This field will be nil for MongoDB versions < 3.6. For versions 3.6 and higher, this will
// be a primitive.Binary with Subtype 4.
UUID *primitive.Binary
// A document containing the options used to construct the collection.
Options bson.Raw
// An IndexSpecification instance with details about the collection's _id index. This will be nil if the NameOnly
// option is used and for MongoDB versions < 3.4.
IDIndex *IndexSpecification
}
var _ bson.Unmarshaler = (*CollectionSpecification)(nil)
// unmarshalCollectionSpecification is used to unmarshal BSON bytes from a listCollections command into a
// CollectionSpecification.
type unmarshalCollectionSpecification struct {
Name string `bson:"name"`
Type string `bson:"type"`
Info *struct {
ReadOnly bool `bson:"readOnly"`
UUID *primitive.Binary `bson:"uuid"`
} `bson:"info"`
Options bson.Raw `bson:"options"`
IDIndex *IndexSpecification `bson:"idIndex"`
}
// UnmarshalBSON implements the bson.Unmarshaler interface.
func (cs *CollectionSpecification) UnmarshalBSON(data []byte) error {
var temp unmarshalCollectionSpecification
if err := bson.Unmarshal(data, &temp); err != nil {
return err
}
cs.Name = temp.Name
cs.Type = temp.Type
if cs.Type == "" {
// The "type" field is only present on 3.4+ because views were introduced in 3.4, so we implicitly set the
// value to "collection" if it's empty.
cs.Type = "collection"
}
if temp.Info != nil {
cs.ReadOnly = temp.Info.ReadOnly
cs.UUID = temp.Info.UUID
}
cs.Options = temp.Options
cs.IDIndex = temp.IDIndex
return nil
}