...

Source file src/github.com/go-kivik/kivik/v4/couchdb/find.go

Documentation: github.com/go-kivik/kivik/v4/couchdb

     1  // Licensed under the Apache License, Version 2.0 (the "License"); you may not
     2  // use this file except in compliance with the License. You may obtain a copy of
     3  // the License at
     4  //
     5  //  http://www.apache.org/licenses/LICENSE-2.0
     6  //
     7  // Unless required by applicable law or agreed to in writing, software
     8  // distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
     9  // WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
    10  // License for the specific language governing permissions and limitations under
    11  // the License.
    12  
    13  package couchdb
    14  
    15  import (
    16  	"context"
    17  	"encoding/json"
    18  	"fmt"
    19  	"net/http"
    20  
    21  	"github.com/go-kivik/kivik/v4/couchdb/chttp"
    22  	"github.com/go-kivik/kivik/v4/driver"
    23  )
    24  
    25  const (
    26  	pathIndex = "_index"
    27  )
    28  
    29  func (d *db) CreateIndex(ctx context.Context, ddoc, name string, index interface{}, options driver.Options) error {
    30  	opts := map[string]interface{}{}
    31  	options.Apply(opts)
    32  	reqPath := partPath(pathIndex)
    33  	options.Apply(reqPath)
    34  	indexObj, err := deJSONify(index)
    35  	if err != nil {
    36  		return err
    37  	}
    38  	parameters := struct {
    39  		Index interface{} `json:"index"`
    40  		Ddoc  string      `json:"ddoc,omitempty"`
    41  		Name  string      `json:"name,omitempty"`
    42  	}{
    43  		Index: indexObj,
    44  		Ddoc:  ddoc,
    45  		Name:  name,
    46  	}
    47  	chttpOpts := &chttp.Options{
    48  		Body: chttp.EncodeBody(parameters),
    49  	}
    50  	_, err = d.Client.DoError(ctx, http.MethodPost, d.path(reqPath.String()), chttpOpts)
    51  	return err
    52  }
    53  
    54  func (d *db) GetIndexes(ctx context.Context, options driver.Options) ([]driver.Index, error) {
    55  	opts := map[string]interface{}{}
    56  	options.Apply(opts)
    57  	reqPath := partPath(pathIndex)
    58  	options.Apply(reqPath)
    59  	var result struct {
    60  		Indexes []driver.Index `json:"indexes"`
    61  	}
    62  	err := d.Client.DoJSON(ctx, http.MethodGet, d.path(reqPath.String()), nil, &result)
    63  	return result.Indexes, err
    64  }
    65  
    66  func (d *db) DeleteIndex(ctx context.Context, ddoc, name string, options driver.Options) error {
    67  	opts := map[string]interface{}{}
    68  	options.Apply(opts)
    69  	if ddoc == "" {
    70  		return missingArg("ddoc")
    71  	}
    72  	if name == "" {
    73  		return missingArg("name")
    74  	}
    75  	reqPath := partPath(pathIndex)
    76  	options.Apply(reqPath)
    77  	path := fmt.Sprintf("%s/%s/json/%s", reqPath, ddoc, name)
    78  	_, err := d.Client.DoError(ctx, http.MethodDelete, d.path(path), nil)
    79  	return err
    80  }
    81  
    82  func (d *db) Find(ctx context.Context, query interface{}, options driver.Options) (driver.Rows, error) {
    83  	opts := map[string]interface{}{}
    84  	options.Apply(opts)
    85  	reqPath := partPath("_find")
    86  	options.Apply(reqPath)
    87  	chttpOpts := &chttp.Options{
    88  		GetBody: chttp.BodyEncoder(query),
    89  		Header: http.Header{
    90  			chttp.HeaderIdempotencyKey: []string{},
    91  		},
    92  	}
    93  	resp, err := d.Client.DoReq(ctx, http.MethodPost, d.path(reqPath.String()), chttpOpts)
    94  	if err != nil {
    95  		return nil, err
    96  	}
    97  	if err = chttp.ResponseError(resp); err != nil {
    98  		return nil, err
    99  	}
   100  	return newFindRows(ctx, resp.Body), nil
   101  }
   102  
   103  type queryPlan struct {
   104  	DBName   string                 `json:"dbname"`
   105  	Index    map[string]interface{} `json:"index"`
   106  	Selector map[string]interface{} `json:"selector"`
   107  	Options  map[string]interface{} `json:"opts"`
   108  	Limit    int64                  `json:"limit"`
   109  	Skip     int64                  `json:"skip"`
   110  	Fields   fields                 `json:"fields"`
   111  	Range    map[string]interface{} `json:"range"`
   112  }
   113  
   114  type fields []interface{}
   115  
   116  func (f *fields) UnmarshalJSON(data []byte) error {
   117  	if string(data) == `"all_fields"` {
   118  		return nil
   119  	}
   120  	var i []interface{}
   121  	if err := json.Unmarshal(data, &i); err != nil {
   122  		return err
   123  	}
   124  	newFields := make([]interface{}, len(i))
   125  	copy(newFields, i)
   126  	*f = newFields
   127  	return nil
   128  }
   129  
   130  func (d *db) Explain(ctx context.Context, query interface{}, options driver.Options) (*driver.QueryPlan, error) {
   131  	opts := map[string]interface{}{}
   132  	options.Apply(opts)
   133  	reqPath := partPath("_explain")
   134  	options.Apply(reqPath)
   135  	chttpOpts := &chttp.Options{
   136  		GetBody: chttp.BodyEncoder(query),
   137  		Header: http.Header{
   138  			chttp.HeaderIdempotencyKey: []string{},
   139  		},
   140  	}
   141  	var plan queryPlan
   142  	if err := d.Client.DoJSON(ctx, http.MethodPost, d.path(reqPath.String()), chttpOpts, &plan); err != nil {
   143  		return nil, err
   144  	}
   145  	return &driver.QueryPlan{
   146  		DBName:   plan.DBName,
   147  		Index:    plan.Index,
   148  		Selector: plan.Selector,
   149  		Options:  plan.Options,
   150  		Limit:    plan.Limit,
   151  		Skip:     plan.Skip,
   152  		Fields:   plan.Fields,
   153  		Range:    plan.Range,
   154  	}, nil
   155  }
   156  

View as plain text