NoSQL
drift.Backbone.NoSQL.Collection(name): JSON document collections.
Signatures
Insert(doc any) (string, error) // returns a STORAGE KEY, not your _id
Get(id string) (json.RawMessage, error) // looks up the doc's _id FIELD
Read(key string) (json.RawMessage, error) // looks up the STORAGE KEY Insert returned
List(filter map[string]string, limit ...int) ([]json.RawMessage, error) // one page, unmarshal each element
ListAll(filter map[string]string) ([]json.RawMessage, error) // every match, paging until exhausted
ListInOrder(limit ...int) ([]json.RawMessage, error) // one page, in WRITE order, no filter
ListAllInOrder() ([]json.RawMessage, error) // every document in write order, paged
Delete(key string) error // by STORAGE KEY
Drop() errorGo alone adds InsertMany(docs []any) (int, error): one all-or-nothing batch write for documents that must land together, such as an order and its line items. The platform commits the whole chunk or rolls back none of it; the other five SDKs have no equivalent today, so a multi-document write there is still one Insert call per document.
Spelled drift.backbone.nosql.collection(c) in the interpreted SDKs. In Node every call is async, so await it.
Two keys, and they are not interchangeable
Insert returns an internal storage key, not the _id. Read and Delete take that storage key; Get takes your own _id field. Keep whichever one you'll look up by: set an _id on the document and use Get, or hold the key Insert handed back and use Read.
On a deployed slice Insert returns an empty string.
Read with it works on your laptop and fails on a slice: set an _id and use Get instead.Filtering and paging
List is equality-only: the filter matches fields exactly, only one field/value pair is honoured, and only top-level scalars are indexed.
Pass a limit for any collection that grows. Omitting it does not mean "everything": the platform applies its own default of 100 documents and silently returns a short list, with nothing to distinguish "these are all of them" from "these are the first hundred." The platform clamps the limit to 1000 either way.
ListAll reads past that cap: it pages List itself, using a document's storage key as the cursor, until the collection is exhausted. Every matching document lands in memory at once, which is the point for something you need to read whole and a cost worth knowing for anything else, since a function runs under a memory limit.
Only four of the six SDKs let you drive the cursor yourself.
after argument on List directly, so you can resume a paged read from a storage key you already hold. Go and Rust do not expose one there: reach for ListAll (which manages its own cursor internally) to read a collection past one page in those two.Order is write order, and it is a different call
List and ListAll return rows in storage-key order, which is not the order anything was written: the key's counter is not zero-padded, so a collection written 1 through 12 comes back 10, 11, 12, then 1, 2, and on through 9. That is stable and complete, and it is not chronological, and it looks chronological for the first nine documents, long enough to pass a manual test before it breaks on the tenth.
ListInOrder and ListAllInOrder are the read for anything shaped like a log: an event store, a ledger, an activity feed, an outbox, a chat history. Both read the platform's own order index instead of the storage key, so no document's key changes and a cursor you already hold keeps working. Neither takes a filter: the field index carries the same unpadded key the plain scan does, so an ordered, filtered read would need a second index the platform does not keep. Filter in the caller, or give that partition its own collection. ListAllInOrder pages the same way ListAll does, with the same one-collection-in-memory cost.
When what you need is a range or an arbitrary sort, such as WHERE seq > 100 ORDER BY seq, reach for SQL instead: NoSQL's order index only ever walks in the order documents were written.
The Backbone guide has the charset rules and what happens to a value that falls outside them.