github.com/thiagoyeds/go-cloud@v0.26.0/docstore/doc.go (about)

     1  // Copyright 2019 The Go Cloud Development Kit Authors
     2  //
     3  // Licensed under the Apache License, Version 2.0 (the "License");
     4  // you may not use this file except in compliance with the License.
     5  // You may obtain a copy of the License at
     6  //
     7  //     https://www.apache.org/licenses/LICENSE-2.0
     8  //
     9  // Unless required by applicable law or agreed to in writing, software
    10  // distributed under the License is distributed on an "AS IS" BASIS,
    11  // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    12  // See the License for the specific language governing permissions and
    13  // limitations under the License.
    14  
    15  // Package docstore provides a portable way of interacting with a document store.
    16  // Subpackages contain driver implementations of docstore for supported
    17  // services.
    18  //
    19  // See https://gocloud.dev/howto/docstore/ for a detailed how-to guide.
    20  //
    21  //
    22  // Collections
    23  //
    24  // In docstore, documents are grouped into collections, and each document has a key
    25  // that is unique in its collection. You can add, retrieve, modify and delete
    26  // documents by key, and you can query a collection to retrieve documents that match
    27  // certain criteria.
    28  //
    29  //
    30  // Representing Documents
    31  //
    32  // A document is a set of named fields, each with a value. A field's value can be a scalar,
    33  // a list, or a nested document.
    34  //
    35  // Docstore allows you to represent documents as either map[string]interface{} or
    36  // struct pointers. When you represent a document as a map, the fields are map keys
    37  // and the values are map values. Lists are represented with slices. For example,
    38  // here is a document about a book described as a map:
    39  //
    40  //   doc := map[string]interface{}{
    41  //       "Title": "The Master and Margarita",
    42  //       "Author": map[string]interface{}{
    43  //           "First": "Mikhail",
    44  //           "Last": "Bulgakov",
    45  //       },
    46  //       "PublicationYears": []int{1967, 1973},
    47  //   }
    48  //
    49  // Note that the value of "PublicationYears" is a list, and the value of "Author" is
    50  // itself a document.
    51  //
    52  // Here is the same document represented with structs:
    53  //
    54  //   type Book struct {
    55  //       Title            string
    56  //       Author           Name
    57  //       PublicationYears []int
    58  //   }
    59  //
    60  //   type Name struct {
    61  //       First, Last string
    62  //   }
    63  //
    64  //   doc := &Book{
    65  //       Title: "The Master and Margarita",
    66  //       Author: Name{
    67  //           First: "Mikhail",
    68  //           Last:  "Bulgakov",
    69  //       },
    70  //       PublicationYears: []int{1967, 1973},
    71  //   }
    72  //
    73  // You must use a pointer to a struct to represent a document, although structs
    74  // nested inside a document, like the Name struct above, need not be pointers.
    75  //
    76  // Maps are best for applications where you don't know the structure of the
    77  // documents. Using structs is preferred because it enforces some structure on your
    78  // data.
    79  //
    80  // By default, Docstore treats a struct's exported fields as the fields of the
    81  // document. You can alter this default mapping by using a struct tag beginning
    82  // with "docstore:". Docstore struct tags support renaming, omitting fields
    83  // unconditionally, or omitting them only when they are empty, exactly like
    84  // encoding/json. For example, this is the Book struct with different field
    85  // names:
    86  //
    87  //   type Book struct {
    88  //       Title            string `docstore:"title"`
    89  //       Author           Name   `docstore:"author"`
    90  //       PublicationYears []int  `docstore:"pub_years,omitempty"`
    91  //       NumPublications  int    `docstore:"-"`
    92  //   }
    93  //
    94  // This struct describes a document with field names "title", "author" and
    95  // "pub_years". The pub_years field is omitted from the stored document if it has
    96  // length zero. The NumPublications field is never stored because it can easily be
    97  // computed from the PublicationYears field.
    98  //
    99  // Given a document field "Foo" and a struct type document, Docstore's decoder
   100  // will look through the destination struct's field to find (in order of
   101  // preference):
   102  //   - An exported field with a tag of "Foo";
   103  //   - An exported field named "Foo".
   104  //
   105  // Note that unlike encoding/json, Docstore does case-sensitive matching during
   106  // decoding to match the behavior of decoders in most docstore services.
   107  //
   108  //
   109  // Representing Data
   110  //
   111  // Values stored in document fields can be any of a wide range of types. All
   112  // primitive types except for complex numbers are supported, as well as slices and
   113  // maps (the map key type must be a string, an integer, or a type that implements
   114  // encoding.TextMarshaler). In addition, any type that implements
   115  // encoding.BinaryMarshaler or encoding.TextMarshaler is permitted. This set of types
   116  // closely matches the encoding/json package (see https://golang.org/pkg/encoding/json).
   117  //
   118  // Times deserve special mention. Docstore can store and retrieve values of type
   119  // time.Time, with two caveats. First, the timezone will not be preserved. Second,
   120  // Docstore guarantees only that time.Time values are represented to millisecond
   121  // precision. Many services will do better, but if you need to be sure that times
   122  // are stored with nanosecond precision, convert the time.Time to another type before
   123  // storing and re-create when you retrieve it. For instance, if you store Unix
   124  // time in nanoseconds using time's UnixNano method, you can get the original
   125  // time back (in the local timezone) with the time.Unix function.
   126  //
   127  //
   128  // Representing Keys
   129  //
   130  // The key of a docstore document is its unique identifier, usually a field.
   131  // Keys never appear alone in the docstore API, only as part of a document. For
   132  // instance, to retrieve a document by key, you pass the Collection.Get method
   133  // a document as a struct pointer or map with the key field populated, and docstore
   134  // populates the rest of that argument with the stored contents. Docstore
   135  // doesn't take zero-value key.
   136  //
   137  // When you open a collection using an OpenCollection method of the
   138  // service-specific driver or a URL, you specify how to extract the key from a
   139  // document.
   140  // Usually, you provide the name of the key field, as in the example below:
   141  //
   142  //   coll, err := memdocstore.OpenCollection("SSN", nil)
   143  //
   144  // Here, the "SSN" field of the document is used as the key. Some drivers let you
   145  // supply a function to extract the key from the document, which can be useful if the
   146  // key is composed of more than one field.
   147  //
   148  //
   149  // Actions
   150  //
   151  // Docstore supports six actions on documents as methods on the Collection type:
   152  //   - Get retrieves a document.
   153  //   - Create creates a new document.
   154  //   - Replace replaces an existing document.
   155  //   - Put puts a document into a collection, replacing it if it is already present.
   156  //   - Update applies a set of modifications to a document.
   157  //   - Delete deletes a document.
   158  //
   159  // Each action acts atomically on a single document. You can execute actions
   160  // individually or you can group them into an action list, like so:
   161  //
   162  //   err := coll.Actions().Put(doc1).Replace(doc2).Get(doc3).Do(ctx)
   163  //
   164  // When you use an action list, docstore will try to optimize the execution of the
   165  // actions. For example, multiple Get actions may be combined into a single "batch
   166  // get" RPC. For the most part, actions in a list execute in an undefined order
   167  // (perhaps concurrently) and independently, but read and write operations on the same
   168  // document are executed in the user-specified order. See the documentation of
   169  // ActionList for details.
   170  //
   171  //
   172  // Revisions
   173  //
   174  // Docstore supports document revisions to distinguish different versions of a
   175  // document and enable optimistic locking. By default, Docstore stores the
   176  // revision in the field named "DocstoreRevision" (stored in the constant
   177  // DefaultRevisionField). Providers give you the option of changing that field
   178  // name.
   179  //
   180  // When you pass a document with a revision field to a write action, Docstore
   181  // will give it a revision at creation time or update the revision value when
   182  // modifying the document. If you don't want Docstore to handle any revision
   183  // logic, simply do not have the revision field in your document.
   184  //
   185  // When you pass a document with a non-nil revision to Put, Replace, Update or
   186  // Delete, Docstore will also compare the revision of the stored document to
   187  // that of the given document before making the change. It returns an error with
   188  // code FailedPrecondition on mismatch. (See https://gocloud.dev/gcerrors for
   189  // information about error codes.) If modification methods are called on a
   190  // document struct or map a nil revision field, then no revision checks are
   191  // performed, and changes are forced blindly, but a new revision will still be
   192  // given for the document. For example, if you call Get to retrieve a document
   193  // with a revision, then later perform a write action with that same document,
   194  // it will fail if the document was changed since the Get.
   195  //
   196  // Since different services use different types for revisions, revision fields
   197  // of unspecified type must be handled. When defining a document struct,
   198  // define the field to be of type interface{}. For example,
   199  //
   200  //   type User {
   201  //       Name             string
   202  //       DocstoreRevision interface{}
   203  //   }
   204  //
   205  //
   206  // Queries
   207  //
   208  // Docstore supports querying within a collection. Call the Query method on
   209  // Collection to obtain a Query value, then build your query by calling Query methods
   210  // like Where, Limit and so on. Finally, call the Get method on the query to execute it.
   211  // The result is an iterator, whose use is described below.
   212  //
   213  //   iter := coll.Query().Where("size", ">", 10).Limit(5).Get(ctx)
   214  //
   215  // The Where method defines a filter condition, much like a WHERE clause in SQL.
   216  // Conditions are of the form "field op value", where field is any document field
   217  // path (including dot-separated paths), op is one of "=", ">", "<", ">=" or "<=",
   218  // and value can be any value.
   219  //
   220  //   iter := coll.Query().Where("Author.Last", "=", "Bulgakov").Limit(3).Get(ctx)
   221  //
   222  // You can make multiple Where calls. In some cases, parts of a Where clause may be
   223  // processed in the driver rather than natively by the backing service, which may have
   224  // performance implications for large result sets. See the driver package
   225  // documentation for details.
   226  //
   227  // Use the DocumentIterator returned from Query.Get by repeatedly calling its Next
   228  // method until it returns io.EOF. Always call Stop when you are finished with an
   229  // iterator. It is wise to use a defer statement for this.
   230  //
   231  //   iter := coll.Query().Where("size", ">", 10).Limit(5).Get(ctx)
   232  //   defer iter.Stop()
   233  //   for {
   234  //       m := map[string]interface{}{}
   235  //       err := iter.Next(ctx, m)
   236  //       if err == io.EOF {
   237  //           break
   238  //       }
   239  //       if err != nil {
   240  //           return err
   241  //       }
   242  //       fmt.Println(m)
   243  //   }
   244  //
   245  //
   246  // Errors
   247  //
   248  // The errors returned from this package can be inspected in several ways:
   249  //
   250  // The Code function from https://gocloud.dev/gcerrors will return an error code, also
   251  // defined in that package, when invoked on an error.
   252  //
   253  // The Collection.ErrorAs method can retrieve the underlying driver error from
   254  // the returned error. See the specific driver's package doc for the supported
   255  // types.
   256  //
   257  //
   258  // OpenCensus Integration
   259  //
   260  // OpenCensus supports tracing and metric collection for multiple languages and
   261  // backend providers. See https://opencensus.io.
   262  //
   263  // This API collects OpenCensus traces and metrics for the following methods:
   264  //  - ActionList.Do
   265  //  - Query.Get (for the first query only; drivers may make additional calls while iterating over results)
   266  // All trace and metric names begin with the package import path.
   267  // The traces add the method name.
   268  // For example, "gocloud.dev/docstore/ActionList.Do".
   269  // The metrics are "completed_calls", a count of completed method calls by driver,
   270  // method and status (error code); and "latency", a distribution of method latency
   271  // by driver and method.
   272  // For example, "gocloud.dev/docstore/latency".
   273  //
   274  // To enable trace collection in your application, see "Configure Exporter" at
   275  // https://opencensus.io/quickstart/go/tracing.
   276  // To enable metric collection in your application, see "Exporting stats" at
   277  // https://opencensus.io/quickstart/go/metrics.
   278  package docstore // import "gocloud.dev/docstore"