N1QL + Go + JSON Marshaling
Developed by Couchbase for use with Couchbase Server, N1QL provides a common query language and JSON-based data model for distributed document-oriented databases. N1QL is a powerful and expressive query language. Among the numerous benefits N1QL provides, it allows the developer a rich ad hoc query experience. In Go, it's easiest to interact with JSON when the schema/structure of the document is known in advance–what happens when queries are built dynamically within the application, at run time? What happens if the results are not strongly typed into a well defined schema? What are the strategies for interacting with an unknown JSON structure in Go? Let's answer these questions by examining three common usage patterns for issuing queries with N1QL in Couchbase.
The code for this blog, along with several other useful examples can be found in our developer guide repository on github. For each of the three examples discussed in this blog, we'll be using the travel-sample bucket in Couchbase, and the Go SDK. The travel-sample dataset comes standard with every instance of Couchbase. It contains a broad collection of airports, airlines, flights, and points of interest JSON documents that are great for prototyping applications with. If you've installed Couchbase on your development machine and you don't have the travel-sample bucket configured,that's okay. It's really easy to load any time you want to use it. From the admin ui, just click on the “settings” tab->”sample buckets” and check the box “travel-sample”. Also, we'll need to install the Go SDK, which can be referenced in your go application in the import section by: “github.com/couchbase/gocb”. Thats all there is to it!
To show the power and flexibility of Couchbase and the N1QL query language, we're going to use an intentionally ambiguous and open ended query. We're going to retrieve any document that has an airport or name that contains a specific character string.
Bootstrap the Application
Remember, always instantiate Couchbase once in your application once and use it as a reference throughout your application. This allows Couchbase to operate asynchronously while saving time not having to spin up/tear down new connections to the cluster each time. This also ensures your application will become aware of any topology changes as they happen. Our main func with the connection to Couchbase and request handlers is build as follows:
Case 1 Strongly Typed (I know what I am looking for!)
In a perfect world, where we know exactly what users will be querying, and we know they'll be doing it in a very structured manner we can setup a strict schema that our results can fold into. First we setup a struct:
The beauty of JSON in Go is that it's natively supported–just like Couchbase. No matter what the structure of the JSON Documents returned by the query, we can “filter” for a strict schema used by the application by iterating through the results. As we iterate through, if the current result document matches what's defined in our JSON struct it will be added to the array of return documents. Other fields that are superfluous are ignored
The array is then marshalled into JSON and sent back as the response. If we issue a request to our api for all airports with Portland in the title: curl http://localhost:3000/api/query/typed?search=Portland we get an array of strongly typed/defined JSON documents back in the response:
Case 2 Untyped (I am not exactly sure–just give me everything!)
Unfortunately not everything fits into explicit schemas and strongly typed structures. Sometimes we might need to issue a query that returns a wide array of document with different schemas. Consider the same query, but lets assume our front end framework wants to find any airport, airline, or point of interest with Portland in the name. The flexibility of Go means we can just iterate through the query results and stream each document into an array of interface variables. We don't need to know the schema in advance.
The resulting mix of divergent schemas is marhsalled and sent back in the response. If we issue a request to our api curl http://localhost:3000/api/query/untyped?search=Portland a diverse array of different schemas are returned in the response.
Case 3 Retrieve One (I just want the first one back!)
Lets take the last example, and simplify it–lets just return the first item in the query results. The Go sdk has a method for that in N1QL, “.One()”
When we issue a request to http://localhost:3000/api/query/one?search=Portland, we can verify that only one result is returned back in the response
The combination of Couchbase, N1QL and Go is an incredibly efficient and streamlined environment that is perfect for building your next Go application. There are plenty of examples within the developer guide, and lots of getting started information on the website. Tweet us @Couchbase–tell us what you're doing with Couchbase and Go!