Result Sets
Description — How to use Couchbase Lite Query’s Result Sets
Related Content — QueryBuilder | SQL++ for Mobile | Predictive Queries | Live Queries | Indexing
Query Execution
The execution of a Couchbase Lite for Swift’s database query returns an array of results, a result set.
Each row of the result set represents the data returned from a document that met the conditions defined by the WHERE
statement of your query.
The composition of each row is determined by the SelectResult
expressions provided in the SELECT
statement.
Returned Results
The types of SelectResult formats you may encounter include those generated by :
-
QueryBuilder.select(SelectResult.all())
— Using All -
QueryBuilder.select(SelectResult.expression(Meta.id))
— Using Doc Id Metadata such as the_id
-
QueryBuilder.select(SelectResult.property("myProp"))
— Using Specific Properties
Return All Document Properties
The SelectResult returned by SelectResult.all()
is a dictionary object, with the database name as the key and the document properties as an array of key-value pairs
[
{
"travel-sample": { (1)
"callsign": "MILE-AIR",
"country": "United States",
"iata": "Q5",
"icao": "MLA",
"id": 10,
"name": "40-Mile Air",
"type": "airline"
}
},
{
"travel-sample": { (2)
"callsign": "ALASKAN-AIR",
"country": "United States",
"iata": "AA",
"icao": "AAA",
"id": 10,
"name": "Alaskan Airways",
"type": "airline"
}
}
]
Return Document Id Only
The SelectResult returned by queries using a SelectResult expression of the form SelectResult.expression(Meta.id)
comprises a dictionary object with ID
as the key and the ID value as the value.
[
{
"id": "hotel123"
},
{
"id": "hotel456"
},
]
Return Specific Properties Only
The SelectResult returned by queries using one or more SelectResult expressions of the form SelectResult.expression(property("name")) )
comprises a key-value pair for each SelectResult expression in the query.
The key being the property name.
[
{ (1)
"id": "hotel123",
"type": "hotel",
"name": "Hotel Ghia"
},
{ (2)
"id": "hotel456",
"type": "hotel",
"name": "Hotel Deluxe",
}
]
Processing Results
Access Document Properties - All Properties | Access Document Properties - ID | Access Document Properties - Selected Properties
To retrieve the results of your query, you need to execute it using Query.execute
.
The output from the execution is an array, with each array element representing the data from a document that matched your search criteria.
To unpack the results you need to iterate through this array. Alternatively, you can convert the result to a JSON string — see:
Access Document Properties - All Properties
Here we look at how to access document properties when you have used SelectResult.all.
In this case each array element is a dictionary structure with the database name as its key. The properties are presented in the value as an array of key-value pairs (property name/property value).
You access the retrieved document properties by converting each row’s value, in turn, to a dictionary — as shown in Example 4.
let results = try query.execute()
for row in results {
let docsProps = row.dictionary(at: 0)! (1)
let docid = docsProps.string(forKey: "id")
let name = docsProps.string(forKey: "name")
let type = docsProps.string(forKey: "type")
let city = docsProps.string(forKey: "city")
print("\(docid): \(name), \(type), \(city)")
let hotel = row.dictionary(at: 0)! (2)
guard let hotelId = hotel.string(forKey: "id") else {
continue
}
hotels[hotelId] = hotel
}
1 | Here we get the dictionary of document properties using the database name as the key. You can add this dictionary to an array of returned matches, for processing elsewhere in the app. |
2 | Alternatively, you can access the document properties here, by using the property names as keys to the dictionary object. |
Access Document Properties - ID
Here we look at how to access document properties when you have returned only the document IDs for documents that matched your selection criteria.
This is something you may do when retrieval of the properties directly by the query may consume excessive amounts of memory and-or processing time.
In this case each array element is a dictionary structure where ID
is the key and the required document ID is the value.
Access the required document properties by retrieving the document from the database using its document ID — as shown in Example 5.
let results = try query.execute()
for result in results {
print(result.toDictionary())
let docId = result.string(forKey: "metaId")! (1)
print("Document Id is -- \(docId)")
// Now you can get the document using the ID
let doc = database.document(withID: docId)!
let hotelId = doc.string(forKey: "id")!
let name = doc.string(forKey: "name")
let city = doc.string(forKey: "city")
let type = doc.string(forKey: "type")
// ... process document properties as required
print("Result properties are: \(hotelId), \(name), \(city), \(type)")
}
1 | Extract the Id value from the dictionary and use it to get the document from the database |
Access Document Properties - Selected Properties
Here we look at how to access properties when you have used SelectResult to get a specific subset of properties.
In this case each array element is an array of key value pairs (property name/property value).
Access the retrieved properties by converting each row into a dictionary — as shown in [ex-acc-specific].
for result in try! query.execute() {
let docID = result.string(forKey: "metaId")!
print("processing doc: \(docID)")
let id = result.string(forKey: "id")!
var hotel = Hotel(id: id)
hotel.name = result.string(forKey: "name")
hotel.city = result.string(forKey: "city")
hotel.type = result.string(forKey: "type")
hotels[id] = hotel
} // end for
JSON Result Sets
Use result.toJSON() to transform your result string into a JSON string, which can easily be serialized or used as required in your application. See <
// In this example the Hotel class is defined using Codable
//
// class Hotel : Codable {
// var id : String = "undefined"
// var type : String = "hotel"
// var name : String = "undefined"
// var city : String = "undefined"
// var country : String = "undefined"
// var description : String? = ""
// var text : String? = ""
// ... other class content
// }
let results = try query.execute()
for row in results {
// get the result into a JSON String
let jsonString = row.toJSON()
let thisJsonObj:Dictionary =
try (JSONSerialization.jsonObject(
with: jsonString.data(using: .utf8)!,
options: .allowFragments)
as? [String: Any])!
// Use Json Object to populate Native object
// Use Codable class to unpack JSON data to native object
var this_hotel: Hotel = try JSONDecoder().decode(Hotel.self, from: jsonString.data(using: .utf8)!) (1)
// ALTERNATIVELY unpack in steps
this_hotel.id = thisJsonObj["id"] as! String
this_hotel.name = thisJsonObj["name"] as! String
this_hotel.type = thisJsonObj["type"] as! String
this_hotel.city = thisJsonObj["city"] as! String
hotels[this_hotel.id] = this_hotel
} // end for
If your query selects ALL then the JSON format will be:
{
database-name: {
key1: "value1",
keyx: "valuex"
}
}
If your query selects a sub-set of available properties then the JSON format will be:
{
key1: "value1",
keyx: "valuex"
}