mongodb

package module
v0.0.0-...-768d359 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Jul 17, 2026 License: BSD-3-Clause Imports: 8 Imported by: 0

README

go-ruby-mongodb/mongodb

mongodb — go-ruby-mongodb

Docs License Go Coverage

A pure-Go (no cgo), MRI-faithful reimplementation of the Ruby mongo gem and the core of the bson gem. Upstream, the mongo gem speaks a hand-written wire protocol and the bson gem's fast path is a C extension. This module binds go.mongodb.org/mongo-driver/v2 — MongoDB's own pure-Go driver and BSON codec — and exposes the gems' Mongo::Client / Mongo::Collection / BSON::* surface on top. The result links statically with CGO_ENABLED=0 on every 64-bit target the go-* ecosystem supports.

It completes the database set alongside go-ruby-sqlite3, go-ruby-pg, and go-ruby-mysql, and is a standalone, reusable module — the MongoDB backend for go-embedded-ruby.

What it is — and isn't. The wire protocol and BSON encoding belong to the driver; this library does not reinvent them. What lives here is the Ruby-shaped facade, the query/pipeline construction, the result→Ruby value mapping, the ordered BSON::Document with byte-exact #to_bson/.from_bson, and the Mongo::Error taxonomy — all deterministic, all the host binding needs to be correct.

Features

Faithful port of the gems' surface, validated against the real driver's BSON codec on every platform:

  • Mongo::ClientNewClient(uri, options...), #database / #[], Ping, Close; WithDatabase (database:) and AppName options.
  • Mongo::Database#name, #collection / #[], #drop.
  • Mongo::Collectioninsert_one / insert_many, find / find_one, update_one / update_many / replace_one, delete_one / delete_many, count_documents, aggregate, distinct, create_index / indexes.
  • Mongo::Cursor — an Enumerable of ordered documents: Each, ToArray, Next, Close.
  • BSON::Document — ordered, string-keyed, with byte-exact ToBSON / DocumentFromBSON and the terse Doc("k", v, ...) builder.
  • BSON::* valuesObjectId (generate / from-string / to-s), Binary, Timestamp, Decimal128, Int32 / Int64 / Double, Regexp, plus nil / datetime / array mapping.
  • Mongo::Error — the gem's error tree (OperationFailure, ConnectionFailure, BulkWriteError, InvalidDocument, duplicate-key …) mapped from the driver's CommandError / WriteException / BulkWriteException.

CGO-free, 100% test coverage, gofmt + go vet clean, and green across the six 64-bit Go targets (amd64, arm64, riscv64, loong64, ppc64le, s390x).

Install

go get github.com/go-ruby-mongodb/mongodb

Usage

package main

import (
	"fmt"

	"github.com/go-ruby-mongodb/mongodb"
)

func main() {
	cli, _ := mongodb.NewClient("mongodb://localhost:27017", mongodb.WithDatabase("test"))
	defer cli.Close()

	people := cli.Database("").Collection("people") // Mongo::Client#[]

	people.InsertOne(mongodb.Doc("name", "Ada", "age", mongodb.Int32(36)))

	cur, _ := people.Find(mongodb.Doc("age", mongodb.Doc("$gte", mongodb.Int32(18))), nil)
	docs, _ := cur.ToArray()
	for _, d := range docs {
		name, _ := d.Get("name")
		fmt.Println(name)
	}

	people.UpdateOne(
		mongodb.Doc("name", "Ada"),
		mongodb.Doc("$set", mongodb.Doc("age", mongodb.Int32(37))),
		nil,
	)
}

BSON type mapping

Ruby (bson gem) This package (BSON::*) Driver wire type
BSON::Document Document (ordered []Element) document
BSON::ObjectId ObjectId objectId
BSON::Binary Binary binData
BSON::Timestamp Timestamp timestamp
BSON::Decimal128 Decimal128 decimal128
BSON::Int32 Int32 int32
BSON::Int64 Int64 int64
BSON::Double Double double
BSON::Regexp Regexp regex
nil / Time / Array nil / DateTime / []any null / date / array

Document#to_bson is produced by the driver's canonical codec, so it is byte-for-byte identical to bson.Marshal of the equivalent native document — verified for every type above, including nested documents and arrays.

Errors

Errors are *mongodb.Error, carrying the mapped Mongo::Error class the host should raise and, where the server sent one, the numeric code:

_, err := coll.InsertMany(docs) // duplicate _id
var e *mongodb.Error
if errors.As(err, &e) {
	fmt.Println(e.Class)             // Mongo::Error::BulkWriteError
	fmt.Println(e.IsDuplicateKey())  // true  (code 11000)
	fmt.Println(e.WriteErrors)       // per-document failures
}

CommandError → OperationFailure, WriteException → OperationFailure, BulkWriteException → BulkWriteError, network/timeout → ConnectionFailure, with unknown driver errors falling back to the base Mongo::Error.

Backend & architectures

The engine is go.mongodb.org/mongo-driver/v2 — MongoDB's own driver and BSON codec, pure Go, no cgo. Every arch below builds and tests with CGO_ENABLED=0:

arch CGO=0 build notes
amd64 native CI lane
arm64 native CI lane
riscv64 qemu-user CI lane
loong64 qemu-user CI lane
ppc64le qemu-user CI lane
s390x qemu-user CI lane (big-endian)

BSON is little-endian on the wire; the driver handles the byte order, so the big-endian s390x lane proves the whole stack round-trips correctly.

Tests & coverage

The suite is fully deterministic and needs no live mongod: the CRUD, aggregation, and index tests drive the real mongo-driver v2 in-process against a canned MockDeployment, so command construction is validated against the real driver while coverage stays at 100% on every OS and cross-arch lane. BSON byte-exactness is checked against the driver's canonical bson.Marshal (plus a pinned golden vector), and the Mongo::Error taxonomy is unit-tested against synthesised driver errors.

An optional round-trip oracle against a real server is gated behind MONGODB_URI and skips itself when unset:

COVERPKG=$(go list ./... | paste -sd, -)
go test -race -coverpkg="$COVERPKG" -coverprofile=cover.out ./...
go tool cover -func=cover.out | tail -1        # 100.0%

MONGODB_URI=mongodb://localhost:27017 go test ./...   # + live round-trip

License

BSD-3-Clause — see LICENSE. Copyright the go-ruby-mongodb/mongodb authors.

WebAssembly

Being pure Go (CGO=0), this library also compiles to WebAssembly — both GOOS=js GOARCH=wasm (browser / Node.js) and GOOS=wasip1 GOARCH=wasm (WASI). CI builds both targets on every push, alongside the six 64-bit native/qemu arches.

GOOS=js     GOARCH=wasm go build ./...   # browser / Node
GOOS=wasip1 GOARCH=wasm go build ./...   # WASI (wasmtime, wasmer, wasmedge, …)

Documentation

Overview

Package mongodb is a pure-Go (CGO=0), MRI-faithful reimplementation of the Ruby mongo gem and the core of the bson gem.

Upstream, the mongo gem drives MongoDB over a hand-written wire protocol and the bson gem's fast path is a C extension. This package instead binds go.mongodb.org/mongo-driver/v2 — MongoDB's own pure-Go driver and BSON codec — and exposes the gem's Ruby surface on top, so the whole stack links statically with CGO_ENABLED=0 on every 64-bit target the go-* ecosystem supports (amd64, arm64, riscv64, loong64, ppc64le, s390x). The wire protocol and BSON encoding are the driver's; this package is the Ruby-shaped facade, the result→Ruby value mapping, and the Mongo::Error taxonomy.

The mongo gem surface

cli, _ := mongodb.NewClient("mongodb://localhost:27017", mongodb.WithDatabase("test"))
db   := cli.Database("test")          // Mongo::Client#database
coll := db.Collection("people")       // Database#[] / Client#[]
coll.InsertOne(mongodb.Doc("name", "Ada", "age", int32(36)))
cur, _ := coll.Find(mongodb.Doc("age", mongodb.Doc("$gte", int32(18))), nil)
docs, _ := cur.ToArray()              // []Document, ordered, string-keyed

Collection mirrors the gem: InsertOne/InsertMany, Find/FindOne, UpdateOne/UpdateMany/ReplaceOne, DeleteOne/DeleteMany, CountDocuments, Aggregate, Distinct, CreateIndex/Indexes.

The bson gem surface

Document is BSON::Document (an ordered, string-keyed document). ObjectId, Binary, Timestamp, Decimal128, Int32, Int64, Double and Regexp mirror the BSON:: value classes; nil, time.Time, and slices map to null, UTC datetime, and array. Document.ToBSON / DocumentFromBSON are the gem's #to_bson / .from_bson byte round-trip, encoded byte-for-byte by the driver's canonical BSON codec.

Determinism and the connection seam

Everything a rbgo binding needs to be correct — BSON encode/decode, ObjectId, query/pipeline construction, result→Ruby mapping, and the error taxonomy — is deterministic and needs no server. The deterministic test suite drives real driver operations in-process against a canned MockDeployment, so it reaches 100% coverage with no live mongod. An optional round-trip suite against a real server is gated behind the MONGODB_URI environment variable and skips when it is unset (so CI, qemu, and Windows lanes stay server-free).

Index

Constants

View Source
const DuplicateKeyCode = 11000

DuplicateKeyCode is the MongoDB server error code for a duplicate key (E11000), the code the gem exposes on a duplicate-key OperationFailure.

Variables

This section is empty.

Functions

This section is empty.

Types

type Binary

type Binary = bson.Binary

Binary is BSON::Binary: a typed binary blob (Subtype + Data).

type Client

type Client struct {
	// contains filtered or unexported fields
}

Client is Mongo::Client: a connection to a MongoDB deployment. Like the gem it is created once and shared; the underlying driver pools connections lazily, so NewClient does not dial and needs no live server.

func NewClient

func NewClient(uri string, opts ...Option) (*Client, error)

NewClient connects to MongoDB, mirroring Mongo::Client.new(uri, options). The uri is a standard mongodb:// or mongodb+srv:// connection string. It returns a *mongodb.Error (class Mongo::Error::*) on failure.

func (*Client) Close

func (c *Client) Close() error

Close disconnects the client and releases pooled connections, the gem's Mongo::Client#close.

func (*Client) Collection

func (c *Client) Collection(name string) *Collection

Collection returns a collection in the client's default database, the gem's Mongo::Client#[].

func (*Client) Database

func (c *Client) Database(name string) *Database

Database returns a handle to a database, the gem's Mongo::Client#database / #use. An empty name resolves to the client's default database (the `database:` option).

func (*Client) Ping

func (c *Client) Ping() error

Ping round-trips a ping command to confirm the deployment is reachable, the gem's Mongo::Client health check. It requires a live server.

type Collection

type Collection struct {
	// contains filtered or unexported fields
}

Collection is Mongo::Collection: a handle to a named collection. Its methods mirror the gem's CRUD, aggregation, and index surface.

func (*Collection) Aggregate

func (c *Collection) Aggregate(pipeline []Document) (*Cursor, error)

Aggregate runs an aggregation pipeline, the gem's Mongo::Collection#aggregate. It returns a Cursor over the stage output.

func (*Collection) CountDocuments

func (c *Collection) CountDocuments(filter Document, opts *CountOptions) (int64, error)

CountDocuments counts documents matching a filter, the gem's Mongo::Collection#count_documents.

func (*Collection) CreateIndex

func (c *Collection) CreateIndex(keys Document, opts *IndexOptions) (string, error)

CreateIndex creates an index over the given key spec, the gem's Mongo::Collection#create_index. It returns the created index name.

func (*Collection) DeleteMany

func (c *Collection) DeleteMany(filter Document) (*DeleteResult, error)

DeleteMany removes every matching document, the gem's Mongo::Collection#delete_many.

func (*Collection) DeleteOne

func (c *Collection) DeleteOne(filter Document) (*DeleteResult, error)

DeleteOne removes the first matching document, the gem's Mongo::Collection#delete_one.

func (*Collection) Distinct

func (c *Collection) Distinct(field string, filter Document) ([]any, error)

Distinct returns the distinct values of a field, the gem's Mongo::Collection#distinct. The values are mapped to the Ruby surface.

func (*Collection) Find

func (c *Collection) Find(filter Document, opts *FindOptions) (*Cursor, error)

Find runs a query, the gem's Mongo::Collection#find. It returns a Cursor, an Enumerable of ordered Documents.

func (*Collection) FindOne

func (c *Collection) FindOne(filter Document, opts *FindOptions) (Document, error)

FindOne returns the first matching document, the gem's Mongo::Collection#find(...).first. It returns a nil Document (and nil error) when nothing matches.

func (*Collection) Indexes

func (c *Collection) Indexes() ([]Document, error)

Indexes lists the collection's indexes, the gem's Mongo::Collection#indexes.

func (*Collection) InsertMany

func (c *Collection) InsertMany(docs []Document) (*InsertManyResult, error)

InsertMany inserts many documents, the gem's Mongo::Collection#insert_many.

func (*Collection) InsertOne

func (c *Collection) InsertOne(doc Document) (*InsertOneResult, error)

InsertOne inserts a single document, the gem's Mongo::Collection#insert_one.

func (*Collection) Name

func (c *Collection) Name() string

Name returns the collection name, the gem's Mongo::Collection#name.

func (*Collection) ReplaceOne

func (c *Collection) ReplaceOne(filter, replacement Document, opts *UpdateOptions) (*UpdateResult, error)

ReplaceOne replaces the first matching document wholesale, the gem's Mongo::Collection#replace_one.

func (*Collection) UpdateMany

func (c *Collection) UpdateMany(filter, update Document, opts *UpdateOptions) (*UpdateResult, error)

UpdateMany applies an update to every matching document, the gem's Mongo::Collection#update_many.

func (*Collection) UpdateOne

func (c *Collection) UpdateOne(filter, update Document, opts *UpdateOptions) (*UpdateResult, error)

UpdateOne applies an update to the first matching document, the gem's Mongo::Collection#update_one.

type CountOptions

type CountOptions struct {
	Limit *int64 // the `limit:` cap
	Skip  *int64 // the `skip:` offset
}

CountOptions are the keyword options of Mongo::Collection#count_documents.

type Cursor

type Cursor struct {
	// contains filtered or unexported fields
}

Cursor is Mongo::Cursor: a lazily-iterated stream of query results, exposed the way the gem's cursor is Enumerable over BSON::Documents. Each yielded document is an ordered Document.

func (*Cursor) Close

func (c *Cursor) Close() error

Close releases the cursor's server-side resources, the gem's Mongo::Cursor#close. It is idempotent and safe to defer.

func (*Cursor) Each

func (c *Cursor) Each(fn func(Document) error) error

Each iterates every remaining document, the gem's Mongo::Cursor#each. Iteration stops and the error is returned if fn returns one; the cursor is always closed.

func (*Cursor) Next

func (c *Cursor) Next(ctx context.Context) (Document, bool, error)

Next advances to the next document, the gem's cursor iteration. It returns the document and true, or a nil document and false when the cursor is exhausted. A server or decode error is returned as a *mongodb.Error.

func (*Cursor) ToArray

func (c *Cursor) ToArray() ([]Document, error)

ToArray drains the cursor into a slice of ordered Documents, the gem's Mongo::Cursor#to_a. The cursor is closed on return.

type Database

type Database struct {
	// contains filtered or unexported fields
}

Database is Mongo::Database: a handle to a named database on a Client.

func (*Database) Collection

func (d *Database) Collection(name string) *Collection

Collection returns a collection handle, the gem's Mongo::Database#collection / #[].

func (*Database) Drop

func (d *Database) Drop() error

Drop drops the database, the gem's Mongo::Database#drop. It requires a live server.

func (*Database) Name

func (d *Database) Name() string

Name returns the database name, the gem's Mongo::Database#name.

type DateTime

type DateTime = bson.DateTime

DateTime is the BSON UTC datetime, milliseconds since the Unix epoch.

func NewDateTime

func NewDateTime(t time.Time) DateTime

NewDateTime builds a BSON DateTime from a time.Time, truncated to milliseconds and normalised to UTC, matching how the gem stores Time.

type Decimal128

type Decimal128 = bson.Decimal128

Decimal128 is BSON::Decimal128: an IEEE-754 decimal128 value.

type DeleteResult

type DeleteResult struct {
	DeletedCount int64
}

DeleteResult is the result of a delete. DeletedCount is the number of documents removed.

type Document

type Document []Element

Document is BSON::Document: an ordered, string-keyed document. Insertion order is preserved on the wire and on read-back, exactly as the gem's ordered hash.

func Doc

func Doc(kv ...any) Document

Doc builds a Document from an alternating key/value list, a terse stand-in for the gem's BSON::Document[...] / hash literal:

mongodb.Doc("age", mongodb.Doc("$gte", int32(18)))

It panics if len(kv) is odd or a key is not a string, mirroring how a Ruby hash literal with a dangling value is a syntax error rather than a runtime value. Use DocumentOf for a checked, error-returning builder.

func DocumentFromBSON

func DocumentFromBSON(b []byte) (Document, error)

DocumentFromBSON parses BSON bytes into an ordered Document, the gem's BSON::Document.from_bson.

func DocumentOf

func DocumentOf(kv ...any) (Document, error)

DocumentOf is the checked form of Doc: it returns an error instead of panicking when the key/value list is malformed.

func (Document) Get

func (d Document) Get(key string) (any, bool)

Get returns the value stored under key and whether it was present. On duplicate keys it returns the first, matching Ruby hash semantics.

func (Document) Keys

func (d Document) Keys() []string

Keys returns the document's keys in order.

func (Document) ToBSON

func (d Document) ToBSON() ([]byte, error)

ToBSON serialises the document to BSON bytes, the gem's BSON::Document#to_bson. The bytes are produced by the driver's canonical codec and are therefore byte-identical to bson.Marshal of the equivalent native document.

type Double

type Double = float64

Double forces the BSON double wire type, like BSON::Double.

type Element

type Element struct {
	Key   string
	Value any
}

Element is a single ordered key/value pair inside a Document, the shape the bson gem yields when iterating a BSON::Document.

type Error

type Error struct {
	// Class is the Mongo::Error subclass this error maps to.
	Class ErrorClass
	// Code is the server error code, or 0 when there is none (e.g. a client-side
	// or network error).
	Code int
	// Message is the human-readable error message.
	Message string
	// WriteErrors holds the per-document write errors of a bulk / InsertMany
	// failure; it is empty for other error classes.
	WriteErrors []WriteError
	// Wrapped is the underlying driver error, if any.
	Wrapped error
}

Error is a MongoDB error carrying the mapped Mongo::Error subclass and, where the server provided one, the numeric error code. It corresponds to a raised Mongo::Error in the gem; Class names the Ruby class the rbgo binding raises.

func (*Error) Error

func (e *Error) Error() string

Error implements the error interface.

func (*Error) IsDuplicateKey

func (e *Error) IsDuplicateKey() bool

IsDuplicateKey reports whether the error is an OperationFailure caused by a duplicate key (server code 11000), the gem's common Mongo::Error::OperationFailure#/E11000/ check.

func (*Error) Unwrap

func (e *Error) Unwrap() error

Unwrap exposes the underlying driver error for errors.Is / errors.As.

type ErrorClass

type ErrorClass string

ErrorClass is the Ruby Mongo::Error subclass an error maps to. The rbgo binding raises the matching Ruby class; from Go it identifies the error category without string matching. Every *Error carries one.

const (
	// ErrBase is the root Mongo::Error.
	ErrBase ErrorClass = "Mongo::Error"
	// ErrOperationFailure is Mongo::Error::OperationFailure, raised for a command
	// or write that the server rejected (including duplicate-key writes).
	ErrOperationFailure ErrorClass = "Mongo::Error::OperationFailure"
	// ErrConnectionFailure is Mongo::Error::ConnectionFailure, a network- or
	// server-selection-level failure.
	ErrConnectionFailure ErrorClass = "Mongo::Error::ConnectionFailure"
	// ErrBulkWriteError is Mongo::Error::BulkWriteError, raised when a bulk /
	// InsertMany operation reports per-document write errors.
	ErrBulkWriteError ErrorClass = "Mongo::Error::BulkWriteError"
	// ErrInvalidDocument is Mongo::Error::InvalidDocument, a client-side document
	// or argument that cannot be serialised.
	ErrInvalidDocument ErrorClass = "Mongo::Error::InvalidDocument"
	// ErrNoServerAvailable is Mongo::Error::NoServerAvailable, raised when no
	// server matching the read preference could be selected.
	ErrNoServerAvailable ErrorClass = "Mongo::Error::NoServerAvailable"
)

The Mongo::Error hierarchy, as raised by the mongo gem. Names match the Ruby class names exactly so the rbgo binding is a direct lookup.

type FindOptions

type FindOptions struct {
	Sort       Document // the `sort:` document
	Projection Document // the `projection:` document
	Limit      *int64   // the `limit:` count
	Skip       *int64   // the `skip:` count
	BatchSize  *int32   // the `batch_size:` hint
}

FindOptions are the keyword options of Mongo::Collection#find. A nil *FindOptions means no options, like calling find with no keywords.

type IndexOptions

type IndexOptions struct {
	Name   string // the `name:` override
	Unique bool   // the `unique:` flag
}

IndexOptions are the keyword options of Mongo::Collection#create_index.

type InsertManyResult

type InsertManyResult struct {
	InsertedIDs []any
}

InsertManyResult is the result of Collection.InsertMany. InsertedIDs holds the _id of each inserted document, in input order.

type InsertOneResult

type InsertOneResult struct {
	InsertedID any
}

InsertOneResult is the result of Collection.InsertOne, the gem's Mongo::Operation::Result for an insert. InsertedID is the _id of the inserted document (an ObjectId generated by the driver when the document had none).

type Int32

type Int32 = int32

Int32 forces the BSON 32-bit integer wire type, like BSON::Int32.

type Int64

type Int64 = int64

Int64 forces the BSON 64-bit integer wire type, like BSON::Int64.

type ObjectId

type ObjectId = bson.ObjectID

ObjectId is BSON::ObjectId: a 12-byte MongoDB object identifier.

func NewObjectId

func NewObjectId() ObjectId

NewObjectId generates a fresh ObjectId, like BSON::ObjectId.new.

func ObjectIdFromString

func ObjectIdFromString(s string) (ObjectId, error)

ObjectIdFromString parses a 24-character hex string into an ObjectId, like BSON::ObjectId.from_string. The error is a *mongodb.Error of class Mongo::Error::InvalidDocument when the string is not valid.

type Option

type Option func(*clientConfig)

Option configures a Client, mirroring a Mongo::Client.new keyword argument.

func AppName

func AppName(name string) Option

AppName sets the application name reported to the server, the gem's `app_name:`.

func WithDatabase

func WithDatabase(name string) Option

WithDatabase sets the default database, the gem's `database:` option. Client.Database with no name (the empty string) then resolves to it.

type Regexp

type Regexp = bson.Regex

Regexp is BSON::Regexp: a BSON regular expression (Pattern + Options).

type Timestamp

type Timestamp = bson.Timestamp

Timestamp is BSON::Timestamp: the internal MongoDB (T, I) timestamp.

type UpdateOptions

type UpdateOptions struct {
	Upsert bool // the `upsert:` flag
}

UpdateOptions are the keyword options shared by update and replace operations.

type UpdateResult

type UpdateResult struct {
	MatchedCount  int64 // documents matched by the filter
	ModifiedCount int64 // documents actually modified
	UpsertedCount int64 // documents inserted by an upsert (0 or 1)
	UpsertedID    any   // _id of an upserted document, or nil
}

UpdateResult is the result of an update, replace, or upsert, mirroring the counts the gem exposes on Mongo::Operation::Result.

type WriteError

type WriteError struct {
	// Index is the position of the offending document in the input slice.
	Index int
	// Code is the server error code for this write.
	Code int
	// Message is the human-readable message for this write.
	Message string
}

WriteError is a single per-document write failure inside a BulkWriteError, mirroring the gem's per-result error detail.

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL