forked from dugancathal/dynago
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathrequest_query.go
170 lines (142 loc) · 4.71 KB
/
request_query.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
package dynago
type queryRequest struct {
TableName string
IndexName string `json:",omitempty"`
// Filtering and query expressions
KeyConditionExpression string `json:",omitempty"`
FilterExpression string `json:",omitempty"`
ProjectionExpression string `json:",omitempty"`
expressionAttributes
Select Select `json:",omitempty"`
ConsistentRead *bool `json:",omitempty"`
ScanIndexForward *bool `json:",omitempty"`
// Limit/offset
Limit uint `json:",omitempty"`
ExclusiveStartKey Document `json:",omitempty"`
ReturnConsumedCapacity CapacityDetail `json:",omitempty"`
}
func newQuery(client *Client, table string) *Query {
req := queryRequest{
TableName: table,
}
return &Query{client, req}
}
// Query is used to return items in the same hash key.
type Query struct {
client *Client
req queryRequest
}
// IndexName specifies to query via a secondary index instead of the table's primary key.
func (q Query) IndexName(name string) *Query {
q.req.IndexName = name
return &q
}
// If strong is true, do a strongly consistent read. (defaults to false)
func (q Query) ConsistentRead(strong bool) *Query {
q.req.ConsistentRead = &strong
return &q
}
// FilterExpression sets a post-filter expression for the results we scan.
func (q Query) FilterExpression(expression string, params ...Params) *Query {
q.req.paramsHelper(params)
q.req.FilterExpression = expression
return &q
}
// KeyConditionExpression sets a condition expression on the key to narrow down what we scan.
func (q Query) KeyConditionExpression(expression string, params ...Params) *Query {
q.req.paramsHelper(params)
q.req.KeyConditionExpression = expression
return &q
}
// ProjectionExpression allows the client to specify which attributes are returned.
func (q Query) ProjectionExpression(expression string, params ...Params) *Query {
q.req.paramsHelper(params)
q.req.ProjectionExpression = expression
return &q
}
// Param is a shortcut to set a single bound parameter.
func (q Query) Param(key string, value interface{}) *Query {
q.req.paramHelper(key, value)
return &q
}
// Params sets multiple bound parameters on this query.
func (q Query) Params(params ...Params) *Query {
q.req.paramsHelper(params)
return &q
}
// ReturnConsumedCapacity enables capacity reporting on this Query.
// Defaults to CapacityNone if not set
func (q Query) ReturnConsumedCapacity(consumedCapacity CapacityDetail) *Query {
q.req.ReturnConsumedCapacity = consumedCapacity
return &q
}
/*
Select specifies how attributes are chosen, or enables count mode.
Most of the time, specifying Select is not required, because the DynamoDB
API does the "right thing" inferring values based on other attributes like
the projection expression, index, etc.
*/
func (q Query) Select(value Select) *Query {
q.req.Select = value
return &q
}
/*
Whether to scan the query index forward (true) or backwards (false).
Defaults to forward (true) if not called.
*/
func (q Query) ScanIndexForward(forward bool) *Query {
q.req.ScanIndexForward = &forward
return &q
}
// Desc makes this query return results descending.
// Equivalent to q.ScanIndexForward(false)
func (q *Query) Desc() *Query {
return q.ScanIndexForward(false)
}
/*
Set the limit on results count.
Note that getting less than `limit` records doesn't mean you're at the last
page of results, that can only be safely asserted if there is no
LastEvaluatedKey on the result.
*/
func (q Query) Limit(limit uint) *Query {
q.req.Limit = limit
return &q
}
/*
Set the start key (effectively the offset cursor)
*/
func (q Query) ExclusiveStartKey(key Document) *Query {
q.req.ExclusiveStartKey = key
return &q
}
// Execute this query and return results.
func (q *Query) Execute() (result *QueryResult, err error) {
return q.client.executor.Query(q)
}
// Query execution logic
func (e *AwsExecutor) Query(q *Query) (result *QueryResult, err error) {
err = e.MakeRequestUnmarshal("Query", &q.req, &result)
if err == nil {
result.query = q
}
return
}
// QueryResult is the result returned from a query.
type QueryResult struct {
query *Query
Items []Document // All the items in the result
Count int // The total number of items in the result
ScannedCount int // How many items were scanned past to get the result
LastEvaluatedKey Document // The offset key for the next page.
// ConsumedCapacity is only set if ReturnConsumedCapacity is given.
ConsumedCapacity *ConsumedCapacity
}
// Next returns a query which get the next page of results when executed.
// Returns nil if there's no next page.
func (qr *QueryResult) Next() (query *Query) {
if qr.LastEvaluatedKey != nil && len(qr.LastEvaluatedKey) > 0 {
query = qr.query.ExclusiveStartKey(qr.LastEvaluatedKey)
}
return
}