github.com/altipla-consulting/ravendb-go-client@v0.1.3/document_query.go (about)

     1  package ravendb
     2  
     3  import (
     4  	"reflect"
     5  	"time"
     6  )
     7  
     8  // Note: Java's IDocumentQueryBase is DocumentQuery
     9  // Note: Java's IDocumentQueryBaseSingle is DocumentQuery
    10  // Note: Java's IDocumentQuery is DocumentQuery
    11  // Note: Java's IFilterDocumentQueryBase is DocumentQuery
    12  
    13  // DocumentQuery describes a query
    14  type DocumentQuery struct {
    15  	*abstractDocumentQuery
    16  }
    17  
    18  // DocumentQueryOptions describes options for creating a query
    19  type DocumentQueryOptions struct {
    20  	// CollectionName and Type are mutually exclusive
    21  	// if Collection is empty string we'll derive name of the collection
    22  	// from Type
    23  	CollectionName string
    24  	Type           reflect.Type
    25  
    26  	// name of the index used for search query
    27  	// if set, CollectionName and Type should not be set
    28  	IndexName string
    29  
    30  	IsMapReduce bool
    31  
    32  	conventions *DocumentConventions
    33  	// rawQuery is mutually exclusive with IndexName and CollectionName/Type
    34  	rawQuery string
    35  
    36  	session      *InMemoryDocumentSessionOperations
    37  	isGroupBy    bool
    38  	declareToken *declareToken
    39  	loadTokens   []*loadToken
    40  	fromAlias    string
    41  }
    42  
    43  func newDocumentQuery(opts *DocumentQueryOptions) *DocumentQuery {
    44  
    45  	var err error
    46  	opts.IndexName, opts.CollectionName, err = processQueryParameters(opts.Type, opts.IndexName, opts.CollectionName, opts.conventions)
    47  	aq := newAbstractDocumentQuery(opts)
    48  	if err != nil {
    49  		aq.err = err
    50  	}
    51  	return &DocumentQuery{
    52  		abstractDocumentQuery: aq,
    53  	}
    54  }
    55  
    56  // SelectFields limits the returned values to one or more fields of the queried type.
    57  func (q *DocumentQuery) SelectFields(projectionType reflect.Type, fieldsIn ...string) *DocumentQuery {
    58  	if q.err != nil {
    59  		return q
    60  	}
    61  	var fields []string
    62  	if len(fieldsIn) == 0 {
    63  		fields = FieldsFor(projectionType)
    64  		if len(fields) == 0 {
    65  			q.err = newIllegalArgumentError("type %T has no exported fields to select", projectionType)
    66  			return q
    67  		}
    68  	} else {
    69  		fields = fieldsIn
    70  	}
    71  
    72  	queryData := &QueryData{
    73  		Fields:      fields,
    74  		Projections: fields,
    75  	}
    76  	res, err := q.createDocumentQueryInternal(projectionType, queryData)
    77  	if err != nil {
    78  		q.err = err
    79  		return q
    80  	}
    81  	return res
    82  }
    83  
    84  // SelectFieldsWithQueryData limits the returned values to one or more fields of the queried type.
    85  func (q *DocumentQuery) SelectFieldsWithQueryData(projectionType reflect.Type, queryData *QueryData) *DocumentQuery {
    86  	// TODO: tests
    87  	// TODO: better name?
    88  	if q.err != nil {
    89  		return q
    90  	}
    91  
    92  	if len(queryData.Fields) != len(queryData.Projections) {
    93  		q.err = newIllegalArgumentError("fields and projections should be of the same size. Have %d and %d elements respectively", len(queryData.Fields), len(queryData.Projections))
    94  		return q
    95  	}
    96  	// TODO: check that fields exist on projectionType
    97  	res, err := q.createDocumentQueryInternal(projectionType, queryData)
    98  	if err != nil {
    99  		q.err = err
   100  		return q
   101  	}
   102  	return res
   103  }
   104  
   105  // Distinct marks query as distinct
   106  func (q *DocumentQuery) Distinct() *DocumentQuery {
   107  	if q.err != nil {
   108  		return q
   109  	}
   110  	q.err = q.distinct()
   111  	return q
   112  }
   113  
   114  // OrderByScore orders results of the query by score
   115  func (q *DocumentQuery) OrderByScore() *DocumentQuery {
   116  	if q.err != nil {
   117  		return q
   118  	}
   119  	q.err = q.orderByScore()
   120  	return q
   121  }
   122  
   123  // OrderByScoreDescending orders results of the query by score
   124  // in descending order
   125  func (q *DocumentQuery) OrderByScoreDescending() *DocumentQuery {
   126  	if q.err != nil {
   127  		return q
   128  	}
   129  	q.err = q.orderByScoreDescending()
   130  	return q
   131  }
   132  
   133  //TBD 4.1  IDocumentQuery<T> explainScores() {
   134  
   135  // WaitForNonStaleResults waits for non-stale results for a given waitTimeout.
   136  // Timeout of 0 means default timeout.
   137  func (q *DocumentQuery) WaitForNonStaleResults(waitTimeout time.Duration) *DocumentQuery {
   138  	if q.err != nil {
   139  		return q
   140  	}
   141  	q.waitForNonStaleResults(waitTimeout)
   142  	return q
   143  }
   144  
   145  func (q *DocumentQuery) AddParameter(name string, value interface{}) *DocumentQuery {
   146  	if q.err != nil {
   147  		return q
   148  	}
   149  	q.err = q.addParameter(name, value)
   150  	return q
   151  }
   152  
   153  func (q *DocumentQuery) AddOrder(fieldName string, descending bool) *DocumentQuery {
   154  	if q.err != nil {
   155  		return q
   156  	}
   157  	return q.AddOrderWithOrdering(fieldName, descending, OrderingTypeString)
   158  }
   159  
   160  func (q *DocumentQuery) AddOrderWithOrdering(fieldName string, descending bool, ordering OrderingType) *DocumentQuery {
   161  	if q.err != nil {
   162  		return q
   163  	}
   164  	if descending {
   165  		return q.OrderByDescendingWithOrdering(fieldName, ordering)
   166  	}
   167  	return q.OrderByWithOrdering(fieldName, ordering)
   168  }
   169  
   170  //TBD expr  IDocumentQuery<T> AddOrder<TValue>(Expression<Func<T, TValue>> propertySelector, bool descending, OrderingType ordering)
   171  
   172  /*
   173   IDocumentQuery<T> AddAfterQueryExecutedListener(Consumer<QueryResult> action) {
   174  	addAfterQueryExecutedListener(action);
   175  	return this;
   176  }
   177  
   178  
   179   IDocumentQuery<T> RemoveAfterQueryExecutedListener(Consumer<QueryResult> action) {
   180  	removeAfterQueryExecutedListener(action);
   181  	return this;
   182  }
   183  
   184  
   185   IDocumentQuery<T> addAfterStreamExecutedListener(Consumer<ObjectNode> action) {
   186  	addAfterStreamExecutedListener(action);
   187  	return this;
   188  }
   189  
   190  
   191   IDocumentQuery<T> removeAfterStreamExecutedListener(Consumer<ObjectNode> action) {
   192  	removeAfterStreamExecutedListener(action);
   193  	return this;
   194  }
   195  */
   196  
   197  // OpenSubclause opens a query sub-clause
   198  func (q *DocumentQuery) OpenSubclause() *DocumentQuery {
   199  	if q.err != nil {
   200  		return q
   201  	}
   202  	q.err = q.openSubclause()
   203  	return q
   204  }
   205  
   206  // CloseSubclause closes a query sub-clause
   207  func (q *DocumentQuery) CloseSubclause() *DocumentQuery {
   208  	if q.err != nil {
   209  		return q
   210  	}
   211  	q.err = q.closeSubclause()
   212  	return q
   213  }
   214  
   215  func (q *DocumentQuery) Search(fieldName string, searchTerms string) *DocumentQuery {
   216  	if q.err != nil {
   217  		return q
   218  	}
   219  	q.err = q.search(fieldName, searchTerms)
   220  	return q
   221  }
   222  
   223  func (q *DocumentQuery) SearchWithOperator(fieldName string, searchTerms string, operator SearchOperator) *DocumentQuery {
   224  	if q.err != nil {
   225  		return q
   226  	}
   227  	q.err = q.searchWithOperator(fieldName, searchTerms, operator)
   228  	return q
   229  }
   230  
   231  //TBD expr  IDocumentQuery<T> Search<TValue>(Expression<Func<T, TValue>> propertySelector, string searchTerms, SearchOperator @operator)
   232  
   233  func (q *DocumentQuery) Intersect() *DocumentQuery {
   234  	if q.err != nil {
   235  		return q
   236  	}
   237  	q.err = q.intersect()
   238  	return q
   239  }
   240  
   241  func (q *DocumentQuery) ContainsAny(fieldName string, values []interface{}) *DocumentQuery {
   242  	if q.err != nil {
   243  		return q
   244  	}
   245  	q.err = q.containsAny(fieldName, values)
   246  	return q
   247  }
   248  
   249  //TBD expr  IDocumentQuery<T> ContainsAny<TValue>(Expression<Func<T, TValue>> propertySelector, IEnumerable<TValue> values)
   250  
   251  func (q *DocumentQuery) ContainsAll(fieldName string, values []interface{}) *DocumentQuery {
   252  	if q.err != nil {
   253  		return q
   254  	}
   255  	q.err = q.containsAll(fieldName, values)
   256  	return q
   257  }
   258  
   259  //TBD expr  IDocumentQuery<T> ContainsAll<TValue>(Expression<Func<T, TValue>> propertySelector, IEnumerable<TValue> values)
   260  
   261  func (q *DocumentQuery) Statistics(stats **QueryStatistics) *DocumentQuery {
   262  	q.statistics(stats)
   263  	return q
   264  }
   265  
   266  func (q *DocumentQuery) UsingDefaultOperator(queryOperator QueryOperator) *DocumentQuery {
   267  	if q.err != nil {
   268  		return q
   269  	}
   270  	q.err = q.usingDefaultOperator(queryOperator)
   271  	return q
   272  }
   273  
   274  func (q *DocumentQuery) NoTracking() *DocumentQuery {
   275  	q.noTracking()
   276  	return q
   277  }
   278  
   279  func (q *DocumentQuery) NoCaching() *DocumentQuery {
   280  	q.noCaching()
   281  	return q
   282  }
   283  
   284  //TBD 4.1  IDocumentQuery<T> showTimings()
   285  
   286  func (q *DocumentQuery) Include(path string) *DocumentQuery {
   287  	q.include(path)
   288  	return q
   289  }
   290  
   291  //TBD expr IDocumentQuery<T> IDocumentQueryBase<T, IDocumentQuery<T>>.Include(Expression<Func<T, object>> path)
   292  
   293  func (q *DocumentQuery) Not() *DocumentQuery {
   294  	q.negateNext()
   295  	return q
   296  }
   297  
   298  func (q *DocumentQuery) Take(count int) *DocumentQuery {
   299  	q.take(count)
   300  	return q
   301  }
   302  
   303  func (q *DocumentQuery) Skip(count int) *DocumentQuery {
   304  	q.skip(count)
   305  	return q
   306  }
   307  
   308  func (q *DocumentQuery) Where(fieldName string, op string, value interface{}) *DocumentQuery {
   309  	if q.err != nil {
   310  		return q
   311  	}
   312  	q.err = q.where(fieldName, op, value)
   313  	return q
   314  }
   315  
   316  func (q *DocumentQuery) WhereLucene(fieldName string, whereClause string) *DocumentQuery {
   317  	if q.err != nil {
   318  		return q
   319  	}
   320  	q.err = q.whereLucene(fieldName, whereClause)
   321  	return q
   322  }
   323  
   324  func (q *DocumentQuery) WhereEquals(fieldName string, value interface{}) *DocumentQuery {
   325  	if q.err != nil {
   326  		return q
   327  	}
   328  	q.err = q.whereEquals(fieldName, value)
   329  	return q
   330  }
   331  
   332  // Exact marks previous Where statement (e.g. WhereEquals or WhereLucene) as exact
   333  func (q *DocumentQuery) Exact() *DocumentQuery {
   334  	if q.err != nil {
   335  		return q
   336  	}
   337  	q.err = q.markLastTokenExact()
   338  	return q
   339  }
   340  
   341  func (q *DocumentQuery) WhereEqualsWithMethodCall(fieldName string, method MethodCall) *DocumentQuery {
   342  	if q.err != nil {
   343  		return q
   344  	}
   345  	q.err = q.whereEqualsWithMethodCall(fieldName, method)
   346  	return q
   347  }
   348  
   349  //TBD expr IDocumentQuery<T> IDocumentQueryBase<T, IDocumentQuery<T>>.WhereEquals<TValue>(Expression<Func<T, TValue>> propertySelector, TValue value, bool exact)
   350  //TBD expr IDocumentQuery<T> IFilterDocumentQueryBase<T, IDocumentQuery<T>>.WhereEquals<TValue>(Expression<Func<T, TValue>> propertySelector, MethodCall value, bool exact)
   351  
   352  func (q *DocumentQuery) WhereEqualsWithParams(whereParams *whereParams) *DocumentQuery {
   353  	if q.err != nil {
   354  		return q
   355  	}
   356  	q.err = q.whereEqualsWithParams(whereParams)
   357  	return q
   358  }
   359  
   360  func (q *DocumentQuery) WhereNotEquals(fieldName string, value interface{}) *DocumentQuery {
   361  	if q.err != nil {
   362  		return q
   363  	}
   364  	q.err = q.whereNotEquals(fieldName, value)
   365  	return q
   366  }
   367  
   368  func (q *DocumentQuery) WhereNotEqualsWithMethod(fieldName string, method MethodCall) *DocumentQuery {
   369  	if q.err != nil {
   370  		return q
   371  	}
   372  	q.err = q.whereNotEqualsWithMethod(fieldName, method)
   373  	return q
   374  }
   375  
   376  //TBD expr IDocumentQuery<T> IDocumentQueryBase<T, IDocumentQuery<T>>.WhereNotEquals<TValue>(Expression<Func<T, TValue>> propertySelector, TValue value, bool exact)
   377  //TBD expr IDocumentQuery<T> IFilterDocumentQueryBase<T, IDocumentQuery<T>>.WhereNotEquals<TValue>(Expression<Func<T, TValue>> propertySelector, MethodCall value, bool exact)
   378  
   379  func (q *DocumentQuery) WhereNotEqualsWithParams(whereParams *whereParams) *DocumentQuery {
   380  	if q.err != nil {
   381  		return q
   382  	}
   383  	q.err = q.whereNotEqualsWithParams(whereParams)
   384  	return q
   385  }
   386  
   387  func (q *DocumentQuery) WhereIn(fieldName string, values []interface{}) *DocumentQuery {
   388  	if q.err != nil {
   389  		return q
   390  	}
   391  	q.err = q.whereIn(fieldName, values)
   392  	return q
   393  }
   394  
   395  //TBD expr  IDocumentQuery<T> WhereIn<TValue>(Expression<Func<T, TValue>> propertySelector, IEnumerable<TValue> values, bool exact = false)
   396  
   397  func (q *DocumentQuery) WhereStartsWith(fieldName string, value interface{}) *DocumentQuery {
   398  	if q.err != nil {
   399  		return q
   400  	}
   401  	q.err = q.whereStartsWith(fieldName, value)
   402  	return q
   403  }
   404  
   405  func (q *DocumentQuery) WhereEndsWith(fieldName string, value interface{}) *DocumentQuery {
   406  	if q.err != nil {
   407  		return q
   408  	}
   409  	q.err = q.whereEndsWith(fieldName, value)
   410  	return q
   411  }
   412  
   413  //TBD expr  IDocumentQuery<T> WhereEndsWith<TValue>(Expression<Func<T, TValue>> propertySelector, TValue value)
   414  
   415  func (q *DocumentQuery) WhereBetween(fieldName string, start interface{}, end interface{}) *DocumentQuery {
   416  	if q.err != nil {
   417  		return q
   418  	}
   419  	q.err = q.whereBetween(fieldName, start, end)
   420  	return q
   421  }
   422  
   423  //TBD expr  IDocumentQuery<T> WhereBetween<TValue>(Expression<Func<T, TValue>> propertySelector, TValue start, TValue end, bool exact = false)
   424  
   425  func (q *DocumentQuery) WhereGreaterThan(fieldName string, value interface{}) *DocumentQuery {
   426  	if q.err != nil {
   427  		return q
   428  	}
   429  	q.err = q.whereGreaterThan(fieldName, value)
   430  	return q
   431  }
   432  
   433  func (q *DocumentQuery) WhereGreaterThanOrEqual(fieldName string, value interface{}) *DocumentQuery {
   434  	if q.err != nil {
   435  		return q
   436  	}
   437  	q.err = q.whereGreaterThanOrEqual(fieldName, value)
   438  	return q
   439  }
   440  
   441  //TBD expr  IDocumentQuery<T> WhereGreaterThan<TValue>(Expression<Func<T, TValue>> propertySelector, TValue value, bool exact = false)
   442  //TBD expr  IDocumentQuery<T> WhereGreaterThanOrEqual<TValue>(Expression<Func<T, TValue>> propertySelector, TValue value, bool exact = false)
   443  
   444  func (q *DocumentQuery) WhereLessThan(fieldName string, value interface{}) *DocumentQuery {
   445  	if q.err != nil {
   446  		return q
   447  	}
   448  	q.err = q.whereLessThan(fieldName, value)
   449  	return q
   450  }
   451  
   452  //TBD expr  IDocumentQuery<T> WhereLessThanOrEqual<TValue>(Expression<Func<T, TValue>> propertySelector, TValue value, bool exact = false)
   453  
   454  func (q *DocumentQuery) WhereLessThanOrEqual(fieldName string, value interface{}) *DocumentQuery {
   455  	if q.err != nil {
   456  		return q
   457  	}
   458  	q.err = q.whereLessThanOrEqual(fieldName, value)
   459  	return q
   460  }
   461  
   462  //TBD expr  IDocumentQuery<T> WhereLessThanOrEqual<TValue>(Expression<Func<T, TValue>> propertySelector, TValue value, bool exact = false)
   463  //TBD expr  IDocumentQuery<T> WhereExists<TValue>(Expression<Func<T, TValue>> propertySelector)
   464  
   465  func (q *DocumentQuery) WhereExists(fieldName string) *DocumentQuery {
   466  	if q.err != nil {
   467  		return q
   468  	}
   469  	q.err = q.whereExists(fieldName)
   470  	return q
   471  }
   472  
   473  //TBD expr IDocumentQuery<T> IFilterDocumentQueryBase<T, IDocumentQuery<T>>.WhereRegex<TValue>(Expression<Func<T, TValue>> propertySelector, string pattern)
   474  
   475  func (q *DocumentQuery) WhereRegex(fieldName string, pattern string) *DocumentQuery {
   476  	if q.err != nil {
   477  		return q
   478  	}
   479  	q.err = q.whereRegex(fieldName, pattern)
   480  	return q
   481  }
   482  
   483  func (q *DocumentQuery) AndAlso() *DocumentQuery {
   484  	if q.err != nil {
   485  		return q
   486  	}
   487  	q.err = q.andAlso()
   488  	return q
   489  }
   490  
   491  func (q *DocumentQuery) OrElse() *DocumentQuery {
   492  	if q.err != nil {
   493  		return q
   494  	}
   495  	q.err = q.orElse()
   496  	return q
   497  }
   498  
   499  func (q *DocumentQuery) Boost(boost float64) *DocumentQuery {
   500  	if q.err != nil {
   501  		return q
   502  	}
   503  	q.err = q.boost(boost)
   504  	return q
   505  }
   506  
   507  func (q *DocumentQuery) Fuzzy(fuzzy float64) *DocumentQuery {
   508  	if q.err != nil {
   509  		return q
   510  	}
   511  	q.err = q.fuzzy(fuzzy)
   512  	return q
   513  }
   514  
   515  func (q *DocumentQuery) Proximity(proximity int) *DocumentQuery {
   516  	if q.err != nil {
   517  		return q
   518  	}
   519  	q.err = q.proximity(proximity)
   520  	return q
   521  }
   522  
   523  func (q *DocumentQuery) RandomOrdering() *DocumentQuery {
   524  	if q.err != nil {
   525  		return q
   526  	}
   527  	q.err = q.randomOrdering()
   528  	return q
   529  }
   530  
   531  func (q *DocumentQuery) RandomOrderingWithSeed(seed string) *DocumentQuery {
   532  	if q.err != nil {
   533  		return q
   534  	}
   535  	q.err = q.randomOrderingWithSeed(seed)
   536  	return q
   537  }
   538  
   539  //TBD 4.1  IDocumentQuery<T> customSortUsing(string typeName, bool descending)
   540  
   541  // GroupBy makes a query grouped by fields
   542  func (q *DocumentQuery) GroupBy(fieldName string, fieldNames ...string) *GroupByDocumentQuery {
   543  	res := newGroupByDocumentQuery(q)
   544  	if q.err == nil {
   545  		q.err = q.groupBy(fieldName, fieldNames...)
   546  	}
   547  
   548  	res.err = q.err
   549  	return res
   550  }
   551  
   552  // GroupByFieldWithMethod makes a query grouped by fields and also allows specifying method
   553  // of grouping for each field
   554  func (q *DocumentQuery) GroupByFieldWithMethod(field *GroupBy, fields ...*GroupBy) *GroupByDocumentQuery {
   555  	res := newGroupByDocumentQuery(q)
   556  	if q.err == nil {
   557  		q.err = q.groupByFieldWithMethod(field, fields...)
   558  	}
   559  	res.err = q.err
   560  	return res
   561  }
   562  
   563  // OrderBy orders query results by a field
   564  func (q *DocumentQuery) OrderBy(field string) *DocumentQuery {
   565  	return q.OrderByWithOrdering(field, OrderingTypeString)
   566  }
   567  
   568  // OrderByWithOrdering orders query results by ordering
   569  func (q *DocumentQuery) OrderByWithOrdering(field string, ordering OrderingType) *DocumentQuery {
   570  	if q.err != nil {
   571  		return q
   572  	}
   573  	q.err = q.orderByWithOrdering(field, ordering)
   574  	return q
   575  }
   576  
   577  //TBD expr  IDocumentQuery<T> OrderBy<TValue>(params Expression<Func<T, TValue>>[] propertySelectors)
   578  
   579  // OrderByDescending orders query by a field in descending order
   580  func (q *DocumentQuery) OrderByDescending(field string) *DocumentQuery {
   581  	return q.OrderByDescendingWithOrdering(field, OrderingTypeString)
   582  }
   583  
   584  // OrderByDescendingWithOrdering orders query by ordering in descending order
   585  func (q *DocumentQuery) OrderByDescendingWithOrdering(field string, ordering OrderingType) *DocumentQuery {
   586  	if q.err != nil {
   587  		return q
   588  	}
   589  	q.err = q.orderByDescendingWithOrdering(field, ordering)
   590  	return q
   591  }
   592  
   593  //TBD expr  IDocumentQuery<T> OrderByDescending<TValue>(params Expression<Func<T, TValue>>[] propertySelectors)
   594  
   595  // AddBeforeQueryExecutedListener adds a listener that will be called before query
   596  // is executed
   597  func (q *DocumentQuery) AddBeforeQueryExecutedListener(action func(*IndexQuery)) int {
   598  	return q.addBeforeQueryExecutedListener(action)
   599  }
   600  
   601  // RemoveBeforeQueryExecutedListener removes a listener registered with AddBeforeQueryExecutedListener
   602  func (q *DocumentQuery) RemoveBeforeQueryExecutedListener(idx int) *DocumentQuery {
   603  	q.removeBeforeQueryExecutedListener(idx)
   604  	return q
   605  }
   606  
   607  // Note: compared to Java, had to move it down to abstractDocumentQuery
   608  func (q *abstractDocumentQuery) createDocumentQueryInternal(resultClass reflect.Type, queryData *QueryData) (*DocumentQuery, error) {
   609  
   610  	var newFieldsToFetch *fieldsToFetchToken
   611  
   612  	if queryData != nil && len(queryData.Fields) > 0 {
   613  		fields := queryData.Fields
   614  
   615  		identityProperty := q.conventions.GetIdentityProperty(resultClass)
   616  
   617  		if identityProperty != "" {
   618  			// make a copy, just in case, because we might modify it
   619  			fields = append([]string{}, fields...)
   620  
   621  			for idx, p := range fields {
   622  				if p == identityProperty {
   623  					fields[idx] = IndexingFieldNameDocumentID
   624  				}
   625  			}
   626  		}
   627  
   628  		sourceAliasReference := getSourceAliasIfExists(resultClass, queryData, fields)
   629  		newFieldsToFetch = createFieldsToFetchToken(fields, queryData.Projections, queryData.isCustomFunction, sourceAliasReference)
   630  	}
   631  
   632  	if newFieldsToFetch != nil {
   633  		q.updateFieldsToFetchToken(newFieldsToFetch)
   634  	}
   635  
   636  	var declareToken *declareToken
   637  	var loadTokens []*loadToken
   638  	var fromAlias string
   639  	if queryData != nil {
   640  		declareToken = queryData.declareToken
   641  		loadTokens = queryData.loadTokens
   642  		fromAlias = queryData.fromAlias
   643  	}
   644  
   645  	opts := &DocumentQueryOptions{
   646  		Type:           resultClass,
   647  		session:        q.theSession,
   648  		IndexName:      q.indexName,
   649  		CollectionName: q.collectionName,
   650  		isGroupBy:      q.isGroupBy,
   651  		declareToken:   declareToken,
   652  		loadTokens:     loadTokens,
   653  		fromAlias:      fromAlias,
   654  	}
   655  	query := newDocumentQuery(opts)
   656  	if query.err != nil {
   657  		return nil, query.err
   658  	}
   659  
   660  	query.queryRaw = q.queryRaw
   661  	query.pageSize = q.pageSize
   662  	query.selectTokens = q.selectTokens
   663  	query.fieldsToFetchToken = q.fieldsToFetchToken
   664  	query.whereTokens = q.whereTokens
   665  	query.orderByTokens = q.orderByTokens
   666  	query.groupByTokens = q.groupByTokens
   667  	query.queryParameters = q.queryParameters
   668  	query.start = q.start
   669  	query.timeout = q.timeout
   670  	query.queryStats = q.queryStats
   671  	query.theWaitForNonStaleResults = q.theWaitForNonStaleResults
   672  	query.negate = q.negate
   673  	//noinspection unchecked
   674  	query.includes = stringArrayCopy(q.includes)
   675  	// TODO: should this be deep copy so that adding/removing in one
   676  	// doesn't affect the other?
   677  	query.beforeQueryExecutedCallback = q.beforeQueryExecutedCallback
   678  	query.afterQueryExecutedCallback = q.afterQueryExecutedCallback
   679  	query.afterStreamExecutedCallback = q.afterStreamExecutedCallback
   680  	query.disableEntitiesTracking = q.disableEntitiesTracking
   681  	query.disableCaching = q.disableCaching
   682  	//TBD 4.1 ShowQueryTimings = ShowQueryTimings,
   683  	//TBD 4.1 query.shouldExplainScores = shouldExplainScores;
   684  	query.isIntersect = q.isIntersect
   685  	query.defaultOperator = q.defaultOperator
   686  
   687  	return query, nil
   688  }
   689  
   690  // AggregateByFacet aggregates the query by a facet
   691  func (q *DocumentQuery) AggregateByFacet(facet FacetBase) *AggregationDocumentQuery {
   692  	res := newAggregationDocumentQuery(q)
   693  	if q.err != nil {
   694  		return res
   695  	}
   696  
   697  	res.err = q.aggregateBy(facet)
   698  	return res
   699  }
   700  
   701  // AggregateByFacets aggregates the query by facets
   702  func (q *DocumentQuery) AggregateByFacets(facets ...*Facet) *AggregationDocumentQuery {
   703  	res := newAggregationDocumentQuery(q)
   704  	if q.err != nil {
   705  		return res
   706  	}
   707  
   708  	for _, facet := range facets {
   709  		if res.err = q.aggregateBy(facet); res.err != nil {
   710  			return res
   711  		}
   712  	}
   713  	return res
   714  }
   715  
   716  // AggregateUsing aggregates the query by facet setup
   717  func (q *DocumentQuery) AggregateUsing(facetSetupDocumentID string) *AggregationDocumentQuery {
   718  	res := newAggregationDocumentQuery(q)
   719  	if q.err != nil {
   720  		return res
   721  	}
   722  	res.err = q.aggregateUsing(facetSetupDocumentID)
   723  	return res
   724  }
   725  
   726  //TBD 4.1 IDocumentQuery<T> IDocumentQueryBase<T, IDocumentQuery<T>>.Highlight(string fieldName, int fragmentLength, int fragmentCount, string fragmentsField)
   727  //TBD 4.1 IDocumentQuery<T> IDocumentQueryBase<T, IDocumentQuery<T>>.Highlight(string fieldName, int fragmentLength, int fragmentCount, out FieldHighlightings highlightings)
   728  //TBD 4.1 IDocumentQuery<T> IDocumentQueryBase<T, IDocumentQuery<T>>.Highlight(string fieldName,string fieldKeyName, int fragmentLength,int fragmentCount,out FieldHighlightings highlightings)
   729  //TBD 4.1 IDocumentQuery<T> IDocumentQueryBase<T, IDocumentQuery<T>>.Highlight<TValue>(Expression<Func<T, TValue>> propertySelector, int fragmentLength, int fragmentCount, Expression<Func<T, IEnumerable>> fragmentsPropertySelector)
   730  //TBD 4.1 IDocumentQuery<T> IDocumentQueryBase<T, IDocumentQuery<T>>.Highlight<TValue>(Expression<Func<T, TValue>> propertySelector, int fragmentLength, int fragmentCount, out FieldHighlightings fieldHighlightings)
   731  //TBD 4.1 IDocumentQuery<T> IDocumentQueryBase<T, IDocumentQuery<T>>.Highlight<TValue>(Expression<Func<T, TValue>> propertySelector, Expression<Func<T, TValue>> keyPropertySelector, int fragmentLength, int fragmentCount, out FieldHighlightings fieldHighlightings)
   732  //TBD 4.1 IDocumentQuery<T> IDocumentQueryBase<T, IDocumentQuery<T>>.SetHighlighterTags(string preTag, string postTag)
   733  //TBD 4.1 IDocumentQuery<T> IDocumentQueryBase<T, IDocumentQuery<T>>.SetHighlighterTags(string[] preTags, string[] postTags)
   734  //TBD expr  IDocumentQuery<T> Spatial(Expression<Func<T, object>> path, Func<SpatialCriteriaFactory, SpatialCriteria> clause)
   735  
   736  func (q *DocumentQuery) Spatial3(fieldName string, clause func(*SpatialCriteriaFactory) SpatialCriteria) *DocumentQuery {
   737  	if q.err != nil {
   738  		return q
   739  	}
   740  	criteria := clause(spatialCriteriaFactoryInstance)
   741  	q.err = q.spatial3(fieldName, criteria)
   742  	return q
   743  }
   744  
   745  func (q *DocumentQuery) Spatial2(field DynamicSpatialField, clause func(*SpatialCriteriaFactory) SpatialCriteria) *DocumentQuery {
   746  	if q.err != nil {
   747  		return q
   748  	}
   749  	criteria := clause(spatialCriteriaFactoryInstance)
   750  	q.err = q.spatial2(field, criteria)
   751  	return q
   752  }
   753  
   754  //TBD expr  IDocumentQuery<T> Spatial(Func<SpatialDynamicFieldFactory<T>, DynamicSpatialField> field, Func<SpatialCriteriaFactory, SpatialCriteria> clause)
   755  //TBD expr IDocumentQuery<T> IDocumentQueryBase<T, IDocumentQuery<T>>.WithinRadiusOf<TValue>(Expression<Func<T, TValue>> propertySelector, float64 radius, float64 latitude, float64 longitude, SpatialUnits? radiusUnits, float64 distanceErrorPct)
   756  
   757  func (q *DocumentQuery) WithinRadiusOf(fieldName string, radius float64, latitude float64, longitude float64) *DocumentQuery {
   758  	if q.err != nil {
   759  		return q
   760  	}
   761  	q.err = q.withinRadiusOf(fieldName, radius, latitude, longitude, "", IndexingSpatialDefaultDistnaceErrorPct)
   762  	return q
   763  }
   764  
   765  func (q *DocumentQuery) WithinRadiusOfWithUnits(fieldName string, radius float64, latitude float64, longitude float64, radiusUnits SpatialUnits) *DocumentQuery {
   766  	if q.err != nil {
   767  		return q
   768  	}
   769  	q.err = q.withinRadiusOf(fieldName, radius, latitude, longitude, radiusUnits, IndexingSpatialDefaultDistnaceErrorPct)
   770  	return q
   771  }
   772  
   773  func (q *DocumentQuery) WithinRadiusOfWithUnitsAndError(fieldName string, radius float64, latitude float64, longitude float64, radiusUnits SpatialUnits, distanceErrorPct float64) *DocumentQuery {
   774  	if q.err != nil {
   775  		return q
   776  	}
   777  	q.err = q.withinRadiusOf(fieldName, radius, latitude, longitude, radiusUnits, distanceErrorPct)
   778  	return q
   779  }
   780  
   781  //TBD expr IDocumentQuery<T> IDocumentQueryBase<T, IDocumentQuery<T>>.RelatesToShape<TValue>(Expression<Func<T, TValue>> propertySelector, string shapeWkt, SpatialRelation relation, float64 distanceErrorPct)
   782  
   783  func (q *DocumentQuery) RelatesToShape(fieldName string, shapeWkt string, relation SpatialRelation) *DocumentQuery {
   784  	return q.RelatesToShapeWithError(fieldName, shapeWkt, relation, IndexingSpatialDefaultDistnaceErrorPct)
   785  }
   786  
   787  func (q *DocumentQuery) RelatesToShapeWithError(fieldName string, shapeWkt string, relation SpatialRelation, distanceErrorPct float64) *DocumentQuery {
   788  	if q.err != nil {
   789  		return q
   790  	}
   791  	q.err = q.spatial(fieldName, shapeWkt, relation, distanceErrorPct)
   792  	return q
   793  }
   794  
   795  // OrderByDistanceLatLongDynamic orders a given field by lat / long
   796  func (q *DocumentQuery) OrderByDistanceLatLongDynamic(field DynamicSpatialField, latitude float64, longitude float64) *DocumentQuery {
   797  	if q.err != nil {
   798  		return q
   799  	}
   800  	q.err = q.orderByDistanceLatLongDynamic(field, latitude, longitude)
   801  	return q
   802  }
   803  
   804  //TBD expr IDocumentQuery<T> IDocumentQueryBase<T, IDocumentQuery<T>>.OrderByDistance(Func<DynamicSpatialFieldFactory<T>, DynamicSpatialField> field, float64 latitude, float64 longitude)
   805  
   806  func (q *DocumentQuery) OrderByDistanceWktDynamic(field DynamicSpatialField, shapeWkt string) *DocumentQuery {
   807  	if q.err != nil {
   808  		return q
   809  	}
   810  	q.err = q.orderByDistanceWktDynamic(field, shapeWkt)
   811  	return q
   812  }
   813  
   814  //TBD expr IDocumentQuery<T> IDocumentQueryBase<T, IDocumentQuery<T>>.OrderByDistance(Func<DynamicSpatialFieldFactory<T>, DynamicSpatialField> field, string shapeWkt)
   815  
   816  //TBD expr IDocumentQuery<T> IDocumentQueryBase<T, IDocumentQuery<T>>.OrderByDistance<TValue>(Expression<Func<T, TValue>> propertySelector, float64 latitude, float64 longitude)
   817  
   818  func (q *DocumentQuery) OrderByDistanceLatLong(fieldName string, latitude float64, longitude float64) *DocumentQuery {
   819  	if q.err != nil {
   820  		return q
   821  	}
   822  	q.err = q.orderByDistanceLatLong(fieldName, latitude, longitude)
   823  	return q
   824  }
   825  
   826  //TBD expr IDocumentQuery<T> IDocumentQueryBase<T, IDocumentQuery<T>>.OrderByDistance<TValue>(Expression<Func<T, TValue>> propertySelector, string shapeWkt)
   827  
   828  func (q *DocumentQuery) OrderByDistanceWkt(fieldName string, shapeWkt string) *DocumentQuery {
   829  	if q.err != nil {
   830  		return q
   831  	}
   832  	q.err = q.orderByDistance3(fieldName, shapeWkt)
   833  	return q
   834  }
   835  
   836  func (q *DocumentQuery) OrderByDistanceDescendingLatLongDynamic(field DynamicSpatialField, latitude float64, longitude float64) *DocumentQuery {
   837  	if q.err != nil {
   838  		return q
   839  	}
   840  	q.err = q.orderByDistanceDescendingLatLongDynamic(field, latitude, longitude)
   841  	return q
   842  }
   843  
   844  //TBD expr IDocumentQuery<T> IDocumentQueryBase<T, IDocumentQuery<T>>.OrderByDistanceDescending(Func<DynamicSpatialFieldFactory<T>, DynamicSpatialField> field, float64 latitude, float64 longitude)
   845  
   846  func (q *DocumentQuery) OrderByDistanceDescendingWktDynamic(field DynamicSpatialField, shapeWkt string) *DocumentQuery {
   847  	if q.err != nil {
   848  		return q
   849  	}
   850  	q.err = q.orderByDistanceDescendingWktDynamic(field, shapeWkt)
   851  	return q
   852  }
   853  
   854  //TBD expr IDocumentQuery<T> IDocumentQueryBase<T, IDocumentQuery<T>>.OrderByDistanceDescending(Func<DynamicSpatialFieldFactory<T>, DynamicSpatialField> field, string shapeWkt)
   855  
   856  //TBD expr IDocumentQuery<T> IDocumentQueryBase<T, IDocumentQuery<T>>.OrderByDistanceDescending<TValue>(Expression<Func<T, TValue>> propertySelector, float64 latitude, float64 longitude)
   857  
   858  func (q *DocumentQuery) OrderByDistanceDescendingLatLong(fieldName string, latitude float64, longitude float64) *DocumentQuery {
   859  	if q.err != nil {
   860  		return q
   861  	}
   862  	q.err = q.orderByDistanceDescendingLatLong(fieldName, latitude, longitude)
   863  	return q
   864  }
   865  
   866  //TBD expr IDocumentQuery<T> IDocumentQueryBase<T, IDocumentQuery<T>>.OrderByDistanceDescending<TValue>(Expression<Func<T, TValue>> propertySelector, string shapeWkt)
   867  
   868  func (q *DocumentQuery) OrderByDistanceDescendingWkt(fieldName string, shapeWkt string) *DocumentQuery {
   869  	if q.err != nil {
   870  		return q
   871  	}
   872  	q.err = q.orderByDistanceDescendingWkt(fieldName, shapeWkt)
   873  	return q
   874  }
   875  
   876  func (q *DocumentQuery) MoreLikeThis(moreLikeThis MoreLikeThisBase) *DocumentQuery {
   877  	if q.err != nil {
   878  		return q
   879  	}
   880  	mlt, err := q.moreLikeThis()
   881  	if err != nil {
   882  		q.err = err
   883  		return q
   884  	}
   885  	defer mlt.Close()
   886  
   887  	mlt.withOptions(moreLikeThis.GetOptions())
   888  
   889  	if mltud, ok := moreLikeThis.(*MoreLikeThisUsingDocument); ok {
   890  		mlt.withDocument(mltud.documentJSON)
   891  	}
   892  
   893  	return q
   894  }
   895  
   896  func (q *DocumentQuery) MoreLikeThisWithBuilder(builder func(IMoreLikeThisBuilderForDocumentQuery)) *DocumentQuery {
   897  	if q.err != nil {
   898  		return q
   899  	}
   900  	f := NewMoreLikeThisBuilder()
   901  	builder(f)
   902  
   903  	moreLikeThis, err := q.moreLikeThis()
   904  	if err != nil {
   905  		q.err = err
   906  		return q
   907  	}
   908  
   909  	moreLikeThis.withOptions(f.GetMoreLikeThis().GetOptions())
   910  
   911  	tmp := f.GetMoreLikeThis()
   912  	if mlt, ok := tmp.(*MoreLikeThisUsingDocument); ok {
   913  		moreLikeThis.withDocument(mlt.documentJSON)
   914  	} else if mlt, ok := tmp.(*MoreLikeThisUsingDocumentForDocumentQuery); ok {
   915  		mlt.GetForDocumentQuery()(q)
   916  	}
   917  	moreLikeThis.Close()
   918  
   919  	return q
   920  }
   921  
   922  func (q *DocumentQuery) SuggestUsing(suggestion SuggestionBase) *SuggestionDocumentQuery {
   923  	res := newSuggestionDocumentQuery(q)
   924  	if q.err != nil {
   925  		res.err = q.err
   926  		return res
   927  	}
   928  
   929  	if q.err = q.suggestUsing(suggestion); q.err != nil {
   930  		res.err = q.err
   931  		return res
   932  	}
   933  	return res
   934  }