-
Notifications
You must be signed in to change notification settings - Fork 298
Query Enhancements
Version 1.0.3 adds some new functionality to view queries:
- Sorting by criteria other than the key order (using
NSSortDescriptor
) - Filtering the result set (using
NSPredicate
) - String or array prefix matching, to find things like "keys starting with 'foo'" or "array keys whose first item is 2014".
-
inclusiveEnd
andinclusiveStart
properties (which default toYES
but can be set toNO
.)
None of these fundamentally alter the map/reduce indexing, and they're all things you could already do yourself, if awkwardly; but they make querying smoother and more intuitive, and they pave the way for future higher level interfaces like Core Data-style fetch requests or Couchbase's N1QL query language.
The new property CBLQuery.sortDescriptors
can be set to an NSArray
of NSSortDescriptor
objects, overriding the default by-key ordering.
A sort descriptor primarily contains a key-path string that specifies an Objective-C property to sort by. As used here, the sort descriptors are being used to sort CBLQueryRow
objects, so the key-paths are interpreted relative to those objects. They should start with "value" to refer to the value, or "key" to refer to the key. A limited form of array indexing is supported, so you can refer to key[1]
or value[0]
if the key or value are arrays. (This only works with indexes from 0 to 3.)
For example, the key-path value.year
would sort NSDictionary-based values by their year
property, and the key-path value[0]
would sort array-based values by their first element. If the value is a scalar like a number or string, you can just use value
by itself to sort by it.
REST API: This feature is not available since it depends on Cocoa classes.
The new property CBLQuery.postFilter
can be set to an NSPredicate
that filters the resulting query rows. The predicate is called on every row returned from the query, and if it returns NO, the row is skipped instead of being added to the CBLQueryEnumerator
.
Since the predicate is called on the CBLQueryRow
instance, it can operate only on properties of that object. Just as described in the previous section, key-paths are interpreted relative to the CBLQueryRow, so they should start with value
to refer to the value, or key
to refer to the key.
Since this filtering happens during querying (and after a query row has been expanded into an object tree) it's inherently much slower than B-tree based index lookups. Don't use it in place of intelligent map-reduce index and query design, or you'll get slow performance!
REST API: This feature is not available since it depends on Cocoa classes.
It's always been possible to constrain a query to match a string or array prefix, but it's been awkward and unintuitive. The new CBLQuery.prefixMatchLevel
property makes it a lot easier. It defaults to 0; for basic prefix matching, set it to 1.
If your keys are strings, to match a prefix you'd set up the query like this:
// Find all keys that start with "f":
query.startKey = query.endKey = @"f";
query.prefixMatchLevel = 1;
Or if your keys are arrays, you can match all keys with the given first item:
// Find all keys whose first item is 2014:
query.startKey = query.endKey = @[@2014];
query.prefixMatchLevel = 1;
The cases where you'd need to set prefixMatchLevel
to a value greater than 1 are those where you're matching a prefix inside an array. For example:
// Find all keys in 2014 whose product name starts with "f":
query.startKey = query.endKey = [@2014, @"f"];
query.prefixMatchLevel = 2; // prefix match on "f...", not [2014, ...]
REST API: This feature is available as the URL query-string property prefix_match_level
.
This one's easy. Setting the property inclusiveEnd
to NO
prevents a row whose key is equal to endKey
from appearing in the result. Same thing for inclusiveStart
and startKey
.
(Those who know CouchDB will recognize inclusiveEnd
, and this property has actually always existed inside Couchbase Lite but was accidentally left out of the public API in 1.0. The inclusiveStart
property is new, though; for some reason CouchDB never added it.)
REST API: These are available as the URL query-string properties inclusive_start
and inclusive_end
.