{"id":4187,"date":"2017-11-14T11:00:49","date_gmt":"2017-11-14T19:00:49","guid":{"rendered":"https:\/\/www.couchbase.com\/blog\/?p=4187"},"modified":"2025-06-13T20:28:08","modified_gmt":"2025-06-14T03:28:08","slug":"sql-for-json-query-interface-couchbase-mobile","status":"publish","type":"post","link":"https:\/\/www.couchbase.com\/blog\/sql-for-json-query-interface-couchbase-mobile\/","title":{"rendered":"Introducing the Query Interface in Couchbase Mobile 2.0"},"content":{"rendered":"<p>The Couchbase Lite 2.0 Release, brings a plethora of <a href=\"https:\/\/developer.couchbase.com\/documentation\/mobile\/2.0\/whatsnew.html\">new features and enhancements<\/a>. We discussed one such enhancement, namely the new replication protocol between in an earlier <a href=\"https:\/\/www.couchbase.com\/blog\/data-replication-couchbase-mobile\/\">blog post on Replication 2.0<\/a>. In this blog post, we will introduce you to another major feature &#8211; the Couchbase Lite Query Interface. The new query interface is based on <a href=\"https:\/\/www.couchbase.com\/products\/n1ql\">N1QL<\/a>, Couchbase\u2019s declarative query language that extends SQL for JSON. If you are familiar with SQL, you will feel right at home with the semantics of the new API.<\/p>\n<p>This post introduces you to the query interface and covers the basics. Refer to the last section of this post for specifics on other related blog posts on more advanced query capabilities.<\/p>\n<p>You can download the Couchbase Mobile 2.0 pre-release builds from our <a href=\"https:\/\/developer.couchbase.com\/documentation\/mobile\/2.0\/whatsnew.html\">downloads<\/a> page.<\/p>\n<p><!--more--><\/p>\n<h3 id=\"background\">Background<\/h3>\n<p>If you were using 1.x versions of Couchbase Mobile, you are probably familiar <a href=\"https:\/\/developer.couchbase.com\/documentation\/mobile\/1.4\/training\/develop\/using-the-database\/index.html#query-documents\">Map-Views<\/a> for creating indexes and queries. In 2.0, you no longer have to create views and map functions! Instead, a simple interface allows you to create indexes and you can use a Query Builder interface to construct your queries. The new query interface is simpler to use and much more powerful in comparison. We will discover some of it\u2019s features in this post.<\/p>\n<h3 id=\"sampleproject\">Sample Project<\/h3>\n<p>While the examples discussed here use Swift for iOS, note that barring some minor differeces, the same query interface is supported on the Android and Windows platforms as well. So with some minor tweaks, you should be able to reuse the examples in this post when working with other platforms.<\/p>\n<p>Follow instructions below if you are interested in a sample Swift Project<\/p>\n<ul>\n<li>Clone the iOS Swift Playground from GitHub\n<pre><code class=\"bash\">$ git clone https:\/\/github.com\/couchbaselabs\/couchbase-lite-ios-api-playground<\/code><\/pre>\n<\/li>\n<li>Follow the installation instructions in the corresponding <a href=\"https:\/\/github.com\/couchbaselabs\/couchbase-lite-ios-a_pi-playground\/blob\/master\/README.md\">README<\/a> file to build and execute the playground.<\/li>\n<\/ul>\n<h3 id=\"sampledatamodel\">Sample Data Model<\/h3>\n<p>We shall use the Travel Sample database located <a href=\"https:\/\/github.com\/couchbaselabs\/couchbase-lite-ios-api-playground\/tree\/master\/travel-sample.cblite2\">here<\/a><\/p>\n<p>The sample data set includes several types of documents as identified by the <code>type<\/code> property in the document. We will focus on documents of <code>type<\/code> <em>\u201chotel\u201d<\/em> and <em>\u201clandmark\u201d<\/em>. The JSON document model is shown below. For simplicity, we have omitted some of the properties from the model below.<\/p>\n<figure><img decoding=\"async\" src=\"https:\/\/www.couchbase.com\/blog\/wp-content\/uploads\/2017\/12\/data_model-2.png\" alt=\"\" \/><\/figure>\n<h3 id=\"thebasics\">The Basics<\/h3>\n<h4 id=\"openingcreatingadatabase\">Opening \/ Creating a Database<\/h4>\n<p>For all the queries below, we will use the <a href=\"https:\/\/developer.couchbase.com\/documentation\/mobile\/2.0\/guides\/couchbase-lite\/native-api\/database\/index.html\"><code>Database<\/code><\/a> API to open\/create CouchbaseLite Database.<\/p>\n<pre><code class=\"swift\">  var options =  DatabaseConfiguration()\r\n  let db = try Database(name: kDBName, config: options)<\/code><\/pre>\n<h4 id=\"indexes\">Indexes<\/h4>\n<p>To speed up read queries, you can create Indexes on properties that you will query on. The performance improvement would be significant on large datasets. Of course, be aware that there will be an increase in storage needs in order to store the indexes and performance of writes can also be impacted. So be cautious of creating too many indexes.<\/p>\n<p>The following example creates a <code>ValueIndex<\/code> on the <code>type<\/code> property of a Document<\/p>\n<pre class=\"wrap:true lang:swift decode:true \">    try db.createIndex(IndexBuilder.valueIndex(items: ValueIndexItem.property(\"type\")),withName: \"typeIndex\")<\/pre>\n<p>The following example creates a <code>ValueIndex<\/code> on <code>type<\/code> and <code>name<\/code> properties of a Document<\/p>\n<pre class=\"wrap:true lang:swift decode:true \">try db.createIndex(IndexBuilder.valueIndex(items: ValueIndexItem.property(\"type\"),ValueIndexItem.property(\"name\")),withName: \"TypeNameIndex\")<\/pre>\n<h4 id=\"fetchingdocumentsfromdatabase\">Fetching documents from database<\/h4>\n<p>A Query in Couchbase Lite is constructed using the Query builder API.<\/p>\n<p>The query below fetches all documents from specfied database. For every document matching the query, all the properties associated with the document are fetched.<\/p>\n<pre class=\"wrap:true lang:swift decode:true \"> let searchQuery = QueryBuilder\r\n        .select(SelectResult.all())\r\n        .from(DataSource.database(db))<\/pre>\n<h4 id=\"fetchingdocumentsfromdatabasewithpagination\">Fetching documents from database with pagination<\/h4>\n<p>This is the structure of a simple query which fetches <code>limit<\/code> number of documents from database starting at specified <code>offset<\/code>. For every document matching the query, all the properties associated with the document are fetched.<\/p>\n<pre class=\"wrap:true lang:swift decode:true \">let searchQuery = QueryBuilder\r\n        .select(SelectResult.all())\r\n        .from(DataSource.database(db))\r\n        .limit(Expression.int(limit),offset: Expression.int(offset))<\/pre>\n<h3 id=\"returnvaluesusingselectresult\">Return Values using SelectResult<\/h3>\n<p>A <code>SelectResult<\/code> represents a single return value of the query statement. Documents in Couchbase Lite comprise of the document properties specified as a Dictionary of Key-Value pairs and associated metadata. The metadata consists of document Id and sequence Id associated with the Document. When you query for a document, the document metadata is not returned by default. You will need to explicitly query for the metadata.<\/p>\n<ul>\n<li><code>SelectResult.all()<\/code>\n<ul>\n<li>Returns all properties associated with a Document<\/li>\n<\/ul>\n<\/li>\n<li><code>SelectResult(Expression)<\/code>\n<ul>\n<li>Returns properties of a Document based on the <code>Expression<\/code>. We discuss the various types of expressions a litte later.<\/li>\n<\/ul>\n<\/li>\n<li><code>SelectResult.expression(Expression.Meta.id)<\/code>\n<ul>\n<li>Returns document Id<\/li>\n<\/ul>\n<\/li>\n<li><code>SelectResult.expression(Expression.Meta.sequence)<\/code>\n<ul>\n<li>Returns sequence Id (used in replications)<\/li>\n<\/ul>\n<\/li>\n<\/ul>\n<p>You can specify a comma separated list of <code>SelectResult<\/code> expressions in the <code>select<\/code> statement of your Query.<br \/>\nFor instance the following select statement queries for the document Id as well as the <code>type<\/code> and <code>name<\/code> properties of the document<\/p>\n<pre class=\"wrap:true lang:swift decode:true \">select(SelectResult.expression(Expression.Meta.id),\r\n                SelectResult.expression(Expression.property(\"type\")),\r\n                SelectResult.expression(Expression.property(\"name\")))<\/pre>\n<h3 id=\"queryexpression\">Query Expression<\/h3>\n<p>A Query Expression is used for constructing a Query Statement<\/p>\n<p>Couchbase Lite includes support for the following <code>Expression<\/code> Types.<\/p>\n<ul>\n<li>Property<\/li>\n<li>Aggregate<\/li>\n<li>String<\/li>\n<li>Collation<\/li>\n<li>Regex<\/li>\n<li>FTS<\/li>\n<li>Null Check Operator<\/li>\n<li>Arithmetic Expressions<\/li>\n<li>Metadata<\/li>\n<li>Pattern Matching<\/li>\n<li>Comparison<\/li>\n<li>Collection<\/li>\n<li>Function<\/li>\n<li>Parameter<\/li>\n<li>Quantified<\/li>\n<li>Bitwise Operator<\/li>\n<\/ul>\n<h3 id=\"processingqueryresponses\">Processing Query Responses<\/h3>\n<p>The results of the query run is an array where every member of the array is an Dictionary \/ Map corresponding to a document that satisfies the query.<\/p>\n<pre class=\"wrap:true lang:swift decode:true\">select(SelectResult.expression(Expression.Meta.id),\r\n                SelectResult.expression(Expression.property(\"type\")),\r\n                SelectResult.expression(Expression.property(\"name\")))<\/pre>\n<ul>\n<li>If you are querying for all the properties of the document using <code>SelectResult.all()<\/code>, then each member of the response array is a Key-Value pair, where the database name is the key and the dictionary corresponding to the Document is the value for the key.For instance,consider the query<\/li>\n<\/ul>\n<pre class=\"wrap:true lang:swift decode:true\">let searchQuery = QueryBuilder\r\n        .select(SelectResult.all())\r\n        .from(DataSource.database(db))\r\n        .limit(Expression.int(limit),offset: Expression.int(offset))<\/pre>\n<ul>\n<li>The results would look something like this (where \u201ctravel-sample\u201d is the name of the database )\n<pre><code class=\"json\">[\r\n    {\r\n        \"travel-sample\": {\r\n            \"callsign\": \"MILE-AIR\",\r\n            \"country\": \"United States\",\r\n            \"iata\": \"Q5\",\r\n            \"icao\": \"MLA\",\r\n            \"id\": 10,\r\n            \"name\": \"40-Mile Air\",\r\n            \"type\": \"airline\"\r\n        }\r\n    },\r\n    {\r\n        \"travel-sample\": {\r\n            \"callsign\": \"TXW\",\r\n            \"country\": \"United States\",\r\n            \"iata\": \"TQ\",\r\n            \"icao\": \"TXW\",\r\n            \"id\": 10123,\r\n            \"name\": \"Texas Wings\",\r\n            \"type\": \"airline\"\r\n        }\r\n    }\r\n]\r\n<\/code><\/pre>\n<p>The code snippet below is an example (in Swift) of how you would process the above results to get the details of the document object<\/p>\n<pre class=\"wrap:true lang:swift decode:true\">for row in try searchQuery.execute() {\r\n        if let dict = row.toDictionary() as? [String:Any], \r\n            let docObject = dict[\"travel-sample\"] as? [String:Any] {\r\n            \/\/ You can now process the document properties \r\n            let name = docObject[\"name\"]\r\n            let type = docObject[\"type\"]\r\n        }\r\n    }<\/pre>\n<p>&nbsp;<\/p>\n<p><code class=\"swift\"><\/code><\/li>\n<li>If you are querying for Id of the document using <code>SelectResult.expression(Expression.Meta.id)<\/code>, then each member of the response array is a Key-Value pair, with <code>\"id\"<\/code> as the key and the the document Id as the value.<br \/>\nFor instance,consider the query<\/li>\n<\/ul>\n<pre class=\"wrap:true lang:swift decode:true\" style=\"padding-left: 30px\"> let searchQuery = QueryBuilder\r\n        .select(SelectResult.expression(Meta.id))\r\n        .from(DataSource.database(db))\r\n        .limit(Expression.int(limit))\r\n<\/pre>\n<ul>\n<li>The results would look something like this &#8211;\n<pre><code class=\"json\">    [\r\n        {\r\n            \"id\": \"airline_112\"\r\n        },\r\n        {\r\n            \"id\": \"airline_189\"\r\n        },\r\n        {\r\n            \"id\": \"airline_1209\"\r\n        }\r\n    ]<\/code><\/pre>\n<p>The code snippet below is an example (in Swift) of how you would process the above results to get the details of the document object using the document Id<\/p>\n<pre class=\"wrap:true lang:swift decode:true\"> for row in try searchQuery.execute() {\r\n        if let dict = row.toDictionary() as? [String:Any], \r\n            let docId  = dict[\"id\"] as? String {\r\n            \/\/ You can now fetch the details of the document using the Id\r\n            let doc = try db.getDocument(docId)\r\n        }     \r\n    }<\/pre>\n<\/li>\n<li>If you are querying for specific property \/ properties of the document using for instance, <code>SelectResult.expression(Expression.property(\"type\")<\/code>, then each member of the response array is a Key-Value pair, with the name of the property \/ properties as the key(s) and the corresponding property values as the valueFor instance,consider the query<\/li>\n<\/ul>\n<pre class=\"wrap:true lang:swift decode:true \"> let searchQuery = QueryBuilder\r\n        .select(SelectResult.expression(Expression.property(\"type\")))\r\n        .from(DataSource.database(db))\r\n        .limit(Expression.int(limit))<\/pre>\n<ul>\n<li>The results would look something like this &#8211;\n<pre><code class=\"json\">    [\r\n        {\r\n            \"type\": \"airline\"\r\n        },\r\n        {\r\n            \"type\": \"airline\"\r\n        },\r\n        {\r\n            \"type\": \"hotel\"\r\n        }\r\n    ]<\/code><\/pre>\n<p>The code snippet below is an example (in Swift) of how you would process the above results to get the property values that you queried for<\/p>\n<pre class=\"wrap:true lang:swift decode:true\"> for row in try searchQuery.execute() {\r\n   if let docObject = row.toDictionary() as? [String:Any]  {\r\n      \/\/ You can now fetch the details of the document using the property name as key\r\n         let type = docObject[\"type\"]\r\n        }     \r\n    }<\/pre>\n<p>You can query for both the Document metadata and properties at the same time by using a comma separated list of <code>SelectResult<\/code> clauses, then each member of the response array is a Key-Value pairs as discussed earlierFor instance,consider the query<\/p>\n<pre class=\"wrap:true lang:swift decode:true\">let searchQuery = QueryBuilder\r\n            .select(SelectResult.expression(Meta.id),\r\n                    SelectResult.expression(Expression.property(\"type\")))\r\n            .from(DataSource.database(db))\r\n            .limit(Expression.int(limit))<\/pre>\n<p>The results would look something like this &#8211;<\/p>\n<pre><code class=\"json\">    [\r\n        {\r\n            \"id\":\"airline_1001\",\r\n            \"type\": \"airline\"\r\n\r\n        },\r\n        {\r\n            \"id\":\"airline_900\",\r\n            \"type\": \"airline\"\r\n        },\r\n        {\r\n            \"id\":\"hotel_1001\",\r\n            \"type\": \"hotel\"\r\n        }\r\n    ]<\/code><\/pre>\n<p>The code snippet below is an example (in Swift) of how you would process the above results to get the property values that you queried for<\/p>\n<pre class=\"wrap:true lang:swift decode:true\"> for row in try searchQuery.execute() {\r\n    if let docObject = row.toDictionary() as? [String:Any]  {\r\n    \/\/ You can now fetch the details of the document using the property name as key\r\n        let type = docObject[\"type\"]\r\n        let docId = docObject[\"id\"]\r\n     }     \r\n }<\/pre>\n<p>&nbsp;<\/p>\n<p><code class=\"swift\"><\/code><\/li>\n<\/ul>\n<h3 id=\"introducingthewhereclause\">Introducing the Where clause<\/h3>\n<p>Similar to SQL, you can use the <code>where<\/code> clause to filter the documents to be returned as part of the query. The <code>select<\/code> statement takes in an <code>Expression<\/code>. You can chain any number of <code>Expressions<\/code> in order to implement sophisticated filtering capabilities.<\/p>\n<h4 id=\"filteringdocumentsbasedonspecificproperty\">Filtering documents based on specific property<\/h4>\n<p>In the example below, we use <code>Property Expression<\/code> type in conjunction with <code>Comparison Expressions<\/code> type to filter documents based on a specific document property. The example below shows the <code>equalTo<\/code> comparison expression.<\/p>\n<p>Note: When referencing a property in a <code>Property Expression<\/code>,we can use key paths (in dotted notation) to specify the path to a nested property.<\/p>\n<pre class=\"wrap:true lang:swift decode:true \"> let searchQuery = QueryBuilder\r\n        .select(SelectResult.all())\r\n        .from(DataSource.database(db))\r\n        .where(Expression.property(\"type\").equalTo(Expression.string(\"hotel\")))\r\n        .limit(Expression.int(limit))<\/pre>\n<p>The list of supported comparison operators include<br \/>\n* lessThan<br \/>\n* notLessThan<br \/>\n* lessThanOrEqualTo<br \/>\n* notLessThanOrEqualTo<br \/>\n* greaterThan<br \/>\n* notGreaterThan<br \/>\n* greaterThanOrEqualTo<br \/>\n* notGreaterThanOrEqualTo<br \/>\n* equalTo<br \/>\n* notEqualTo<\/p>\n<h4 id=\"filteringdocumentsusinglogicalexpressions\">Filtering documents using logical Expressions<\/h4>\n<p>We can use <code>Logical Expression<\/code> to chain together several <code>comparison expressions<\/code>. In the example below, we fetch documents of <code>type<\/code> hotel whose <code>country<\/code> property is equal To <em>\u201cUnited States\u201d<\/em> or <em>\u201cFrance\u201d<\/em> and whose <code>vacancy<\/code> property is <em>true<\/em>. In other words, we are fetching all hotels in the United States or France that have a vacancy.<\/p>\n<pre class=\"wrap:true lang:swift decode:true\">let searchQuery = QueryBuilder\r\n        .select(SelectResult.expression(Meta.id))\r\n        .from(DataSource.database(db))\r\n        .where(Expression.property(\"type\").equalTo(Expression.string(\"hotel\"))\r\n            .and(Expression.property(\"country\").equalTo(Expression.string (\"United States\"))\r\n            .or(Expression.property(\"country\").equalTo(Expression.string (\"France\"))))\r\n            .and(Expression.property(\"vacancy\").equalTo(Expression.boolean(true))))\r\n        .limit(Expression.int(limit))<\/pre>\n<h3 id=\"patternmatching\">Pattern Matching<\/h3>\n<p>The <code>like<\/code> and <code>regex<\/code> expressions can be used for string matching. These perform **case sensitive ** matches. So if you want to make the string matching case insensitive, you would have to use <code>Function.lower<\/code> or <code>Function.upper<\/code> to transform the matched string to lowercase or uppercase equivalents.<\/p>\n<h4 id=\"exactmatch\">Exact Match<\/h4>\n<p>In the example below, we are looking for documents of <code>type<\/code> \u201clandmark\u201d where the <code>name<\/code> property exactly matches the string <em>\u201cRoyal engineers museum\u201d<\/em>. Note that since <code>like<\/code> does a case sensitive match, we used <code>Function.lower<\/code> to transform matched string to lowercase equivalent. So the following query will return <em>\u201clandmark\u201d<\/em> <code>type<\/code> documents with <code>name<\/code> matching <em>\u201cRoyal Engineers Museum\u201d<\/em>, <em>\u201croyal engineers museum\u201d<\/em>, <em>\u201cROYAL ENGINEERS MUSEUM\u201d<\/em> and so on.<\/p>\n<pre class=\"wrap:true lang:swift decode:true \"> let searchQuery = QueryBuilder\r\n        .select(SelectResult.expression(Meta.id),\r\n                SelectResult.expression(Expression.property(\"country\")),\r\n                SelectResult.expression(Expression.property(\"name\")))\r\n        .from(DataSource.database(db))\r\n        .where(Expression.property(\"type\").equalTo(Expression.string(\"landmark\"))\r\n            .and(Function.lower(Expression.property(\"name\")).like(Expression.string(\"royal engineers museum\"))))\r\n        .limit(Expression.int(limit))<\/pre>\n<h4 id=\"wildcardmatch\">Wildcard Match<\/h4>\n<p>We can use <code>%<\/code> sign within a <code>like<\/code> expression to do a wildcard match against zero or more characters. Using wildcards allows you to have some fuzziness in your search string.<\/p>\n<p>In the example below, we are looking for documents of <code>type<\/code> \u201clandmark\u201d where the <code>name<\/code> property matches any string that begins with \u201ceng\u201d followed by zero or more characters, the letter \u201ce\u201d, followed by zero or more characters. Once again, we are using <code>Function.lower<\/code> to make the search case insenstive.<\/p>\n<p>The following query will return <em>\u201clandmark\u201d<\/em> <code>type<\/code> documents with <code>name<\/code> matching <em>\u201cEngineers\u201d<\/em>, <em>\u201cengine\u201d<\/em>, <em>\u201cenglish egg\u201d<\/em> , <em>\u201cEngland Eagle\u201d<\/em> and so on. Notice that the matches may span word boundaries.<\/p>\n<pre class=\"wrap:true lang:swift decode:true\">    let searchQuery = QueryBuilder\r\n        .select(SelectResult.expression(Meta.id),\r\n                SelectResult.expression(Expression.property(\"country\")),\r\n                SelectResult.expression(Expression.property(\"name\")))\r\n        .from(DataSource.database(db))\r\n        .where(Expression.property(\"type\").equalTo(Expression.string(\"landmark\"))\r\n            .and( Function.lower(Expression.property(\"name\")).like(Expression.string(\"%eng%r%\"))))\r\n        .limit(Expression.int(limit))<\/pre>\n<h4 id=\"wildcardcharactermatch\">Wildcard Character Match<\/h4>\n<p>We can use <code>\"_\"<\/code> sign within a <code>like<\/code> expression to do a wildcard match against a single character.<\/p>\n<p>In the example below, we are looking for documents of <code>type<\/code> \u201clandmark\u201d where the <code>name<\/code> property matches any string that begins with \u201ceng\u201d followed by exactly 4 wildcard characters and ending in the letter \u201cr\u201d.<\/p>\n<p>Notice that unlike the previous examples, we are not using <code>Function.lower<\/code> to transform search string to lowercase. So the search will be case senstive.<br \/>\nThe following query will return <em>\u201clandmark\u201d<\/em> <code>type<\/code> documents with <code>name<\/code> matching <em>\u201cEngineer\u201d<\/em>, <em>\u201cEngineer1\u201d<\/em> and so on.<\/p>\n<pre class=\"wrap:true lang:swift decode:true\">let searchQuery = QueryBuilder\r\n        .select(SelectResult.expression(Meta.id),\r\n                SelectResult.expression(Expression.property(\"country\")),\r\n                SelectResult.expression(Expression.property(\"name\")))\r\n        .from(DataSource.database(db))\r\n        .where(Expression.property(\"type\").equalTo(Expression.string(\"landmark\"))\r\n            .and( Expression.property(\"name\")\r\n                .like(Expression.string(\"%Eng____r%\"))))\r\n        .limit(Expression.int(limit))<\/pre>\n<h4 id=\"regexmatch\">Regex Match<\/h4>\n<p>The <code>regex<\/code> expression can be used for case sensitive matches. Similar to wildcard <code>like<\/code> expressions, <code>regex<\/code> expressions based pattern matching allow you to have some fuzziness in your search string.<\/p>\n<p>In the example below, we are looking for documents of <code>type<\/code> \u201clandmark\u201d where the <code>name<\/code> property matches any string (on word boundaries) that begins with \u201ceng\u201d followed by exactly 4 wildcard characters and ending in the letter \u201cr\u201d. Once again, we are using <code>Function.lower<\/code> to make the search case insenstive.<\/p>\n<p>The following query will return <em>\u201clandmark\u201d<\/em> <code>type<\/code> documents with <code>name<\/code> matching <em>\u201cEngine\u201d<\/em>, <em>\u201cengine\u201d<\/em> and so on. Note that the <code>\\b<\/code> specifies that the match must occur on word boundaries.<\/p>\n<pre class=\"wrap:true lang:swift decode:true \">let searchQuery = QueryBuilder\r\n        .select(SelectResult.expression(Meta.id),\r\n        SelectResult.expression(Expression.property(\"name\")) )\r\n        .from(DataSource.database(db))\r\n        .where(Expression.property(\"type\").equalTo(Expression.string(\"landmark\"))\r\n            .and(Function.lower(Expression.property(\"name\")).regex(Expression.string(\"\\\\beng.*r.*\\\\b\"))))\r\n        .limit(Expression.int(limit))<\/pre>\n<h3 id=\"documentsthathavenullormissingproperty\">Documents that have Null Or Missing Property<\/h3>\n<p>One of the features of the query language that sets it apart from SQL is the ability to query for documents which have null or missing properties.<\/p>\n<p>The <code>isNullOrMissing()<\/code> expression is used in conjunction with the <code>Property Expression<\/code> to test if the specified property has a null or missing value. The <code>isNullOrMissing()<\/code> does the reverse.<\/p>\n<p>In the example below, we are looking for all documents in which the <code>email<\/code> property that is null or missing.<\/p>\n<pre class=\"wrap:true lang:swift decode:true \"> let searchQuery = QueryBuilder\r\n        .select(SelectResult.expression(Meta.id),\r\n                SelectResult.expression(Expression.property(\"email\")))\r\n        .from(DataSource.database(db))\r\n        .where(Expression.property(\"email\").isNullOrMissing())\r\n        .limit(Expression.int(limit))<\/pre>\n<h3 id=\"orderingofdocuments\">Ordering of Documents<\/h3>\n<p>It is possible to sort the results of a query based on a given expression result.<\/p>\n<p>The example below returns documents of <code>type<\/code> equal to <em>\u201chotel\u201d<\/em> sorted in ascending order by the value of the <code>title<\/code> property.<\/p>\n<pre class=\"wrap:true lang:swift decode:true \"> let searchQuery = QueryBuilder.select(\r\n            SelectResult.expression(Meta.id),\r\n            SelectResult.expression(Expression.property(\"title\")))\r\n        .from(DataSource.database(db))\r\n    .where(Expression.property(\"type\").equalTo(Expression.string(\"hotel\")))\r\n        .orderBy(Ordering.property(\"title\").ascending())\r\n        .limit(Expression.int(limit))<\/pre>\n<h3 id=\"stringmanipulation\">String Manipulation<\/h3>\n<p>String manipulation capabilities are integral to any data processing. In previous examples, we looked at how the <code>Function.lower<\/code> could be used to transform a string to lowercase equivalent to make case insenstive string comparisons.<\/p>\n<p>Couchbase Lite supports the following string processing functions.<\/p>\n<pre><code class=\"(null)\">    - Function.lower(String Expression)\r\n    - Function.ltrim(String Expression)\r\n    - Function.rtrim(String Expression)\r\n    - Function.trim(String Expression)\r\n    - Function.upper(String Expression)\r\n    - Function.length(String Expression)\r\n    - Function.substring(String Expression, String Expression)\r\n<\/code><\/pre>\n<p>The example below returns documents of where the <code>email<\/code> property contains the substring <em>\u201cnatgeo.org\u201d<\/em>. The <code>name<\/code> property value is converted to uppercase in the response.<\/p>\n<pre class=\"wrap:true lang:swift decode:true \">let searchQuery = QueryBuilder.select(SelectResult.expression(Meta.id),\r\n                SelectResult.expression(Expression.property(\"email\")),\r\n                SelectResult.expression(Expression.property(\"name\")))\r\n        .from(DataSource.database(db))\r\n .where(Function.contains(Expression.property(\"email\"), substring: Expression.string (\"natgeo.org\")))\r\n        .limit(Expression.int(limit))<\/pre>\n<p>&nbsp;<\/p>\n<h4 id=\"collation\">Collation<\/h4>\n<p>Collation functions enhance string comparison and sorting capabilities by supporting unicode strings, locale-aware string manipulation and language specific features like diacritics. You can learn about collation in this <a href=\"https:\/\/github.com\/couchbase\/couchbase-lite-core\/wiki\/JSON-Query-Schema#collation\">writeup <\/a> by Jens Alfke.<\/p>\n<p>The example below defines the Collation rules that the case and accents be ignored. This collator is applied to the string comparison function on the <code>name<\/code> property. The results will include documents where <code>name<\/code> is equal to strings strings like \u201cHotel Novotel Paris La Defense\u201d , \u201cHotel Novotel Paris La D\u00e9fense\u201d and so on.<\/p>\n<pre class=\"wrap:true lang:swift decode:true \">let collator = Collation.unicode()\r\n                .ignoreAccents(true)\r\n                .ignoreCase(true)\r\n\r\nlet searchQuery = QueryBuilder.select(SelectResult.expression(Meta.id),\r\n         SelectResult.expression(Expression.property(\"name\")))\r\n        .from(DataSource.database(db))\r\n     .where(Expression.property(\"type\").equalTo(Expression.string(\"hotel\"))\r\n            .and(Expression.property(\"name\").collate(collator).equalTo(Expression.string (\"Hotel novotel paris la defense\"))))\r\n        .limit(Expression.int(limit))<\/pre>\n<p>There are some limitations in the Collation support &#8211; at the time of writing this post, it cannot be used with pattern matching queries such as <code>like<\/code> and <code>regex<\/code> .<\/p>\n<h3 id=\"stringmanipulation\">Parameterization<\/h3>\n<p>One of the more powerful features of the query interface is the ability to set parameters on a query. This gives you the flexibility to update the parameter values to a query at any point without having to re-create or re-start the query. Changing the query parameters will auto re-start the query and the new parameters will take effect.<\/p>\n<p>Referring to the data model above, lets suppose that you want to fetch documents where the number\u00a0<code>public-likes<\/code>\u00a0is within \u00a0a certain range. In the example below, we are looking for &#8220;hotel&#8221; <code>type<\/code>\u00a0documents where the umber of <code>public-likes<\/code>\u00a0is between 5 and 10.<\/p>\n<pre class=\"wrap:true lang:swift decode:true \">  \/\/ 1. function that corresponds to the number of elements in an array\r\n  let likesCount = ArrayFunction.length(Expression.property(\"public_likes\"))\r\n \/\/ 2. Parameters for specifying lower and upper limits of range\r\n let lowerCount = Expression.parameter(\"lower\")\r\n let upperCount = Expression.parameter(\"upper\")\r\n  \r\n \/\/ 3. Query that takes in parameters\r\n let searchQuery = QueryBuilder\r\n        .select(SelectResult.expression(Meta.id),\r\n                SelectResult.expression(Expression.property(\"name\")),\r\n                SelectResult.expression(likesCount).as(\"NumLikes\")\r\n        )\r\n        .from(DataSource.database(db))\r\n        .where(Expression.property(\"type\").equalTo(Expression.string (\"hotel\"))\r\n            .and(likesCount.between(lowerCount,and: upperCount)))\r\n        .limit(Expression.int(limit))\r\n\r\n   \/\/ 4. Supplying the query parameter values\r\n   let params = Parameters.init().setInt(5, forName: \"lower\").setInt(10, forName: \"upper\")\r\n    searchQuery.parameters = params<\/pre>\n<p>Note that the example above, you may have noticed the use of <code>ArrayFunction<\/code>. Couchbase Lite 2.0 provides us with extensive array manipulation support. This will be discussed future in this <a href=\"https:\/\/www.couchbase.com\/blog\/querying-array-collections-couchbase-mobile\/\">blog post on collections.<\/a><\/p>\n<h3 id=\"whatnext\">What Next<\/h3>\n<p>This blog post gave you a glimpse into the powerful new Query Interface supported in Couchbase Lite 2.0. You can download the Couchbase Mobile 2.0 pre-release builds from our <a href=\"https:\/\/developer.couchbase.com\/documentation\/mobile\/2.0\/whatsnew.html\">downloads<\/a> page.<\/p>\n<p>Here are other Couchbase Mobile Query related posts that may be of interest<br \/>\n&#8211; This <a href=\"https:\/\/www.couchbase.com\/blog\/full-text-search-couchbase-mobile-2-0\/\">blog post<\/a> discusses the Full Text Search capabilities.<br \/>\n&#8211; This <a href=\"https:\/\/www.couchbase.com\/blog\/querying-array-collections-couchbase-mobile\/\">blog post<\/a> discusses how to query array collections<br \/>\n&#8211; This <a href=\"https:\/\/www.couchbase.com\/blog\/join-queries-couchbase-mobile\/\">blog post<\/a> discusses how to do JOIN queries<\/p>\n<p>If\u00a0you have questions or feedback, please leave a comment below or feel free to reach out to me at Twitter\u00a0<a href=\"https:\/\/twitter.com\/rajagp\">@rajagp<\/a>\u00a0or email me\u00a0<a href=\"mailto:priya.rajagopal@couchbase.com\">priya.rajagopal@couchbase.com<\/a>. \u00a0The\u00a0<a href=\"https:\/\/www.couchbase.com\/forums\/\">Couchbase Forums<\/a> are another good place to reach out with\u00a0questions.<\/p>\n<p>&nbsp;<\/p>\n","protected":false},"excerpt":{"rendered":"<p>The Couchbase Lite 2.0 Release, brings a plethora of new features and enhancements. We discussed one such enhancement, namely the new replication protocol between in an earlier blog post on Replication 2.0. In this blog post, we will introduce you [&hellip;]<\/p>\n","protected":false},"author":1423,"featured_media":4188,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"_acf_changed":false,"inline_featured_image":false,"footnotes":""},"categories":[1815,7667,1810,2165,1812],"tags":[1393,2087,1505,1261,1743],"ppma_author":[8948],"class_list":["post-4187","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-best-practices-and-tutorials","category-couchbase-lite","category-couchbase-mobile","category-full-text-search","category-n1ql-query","tag-api","tag-couchbase-mobile-2","tag-index","tag-json","tag-sqlite"],"acf":[],"yoast_head":"<!-- This site is optimized with the Yoast SEO Premium plugin v25.7.1 (Yoast SEO v25.7) - https:\/\/yoast.com\/wordpress\/plugins\/seo\/ -->\n<title>Introducing the Query Interface in Couchbase Mobile 2.0<\/title>\n<meta name=\"description\" content=\"Couchbase Mobile 2.0 supports a new query interface based on N1QL, Couchbase\u2019s declarative query language that extends SQL for JSON.\" \/>\n<meta name=\"robots\" content=\"index, follow, max-snippet:-1, max-image-preview:large, max-video-preview:-1\" \/>\n<link rel=\"canonical\" href=\"https:\/\/www.couchbase.com\/blog\/sql-for-json-query-interface-couchbase-mobile\/\" \/>\n<meta property=\"og:locale\" content=\"en_US\" \/>\n<meta property=\"og:type\" content=\"article\" \/>\n<meta property=\"og:title\" content=\"Introducing the Query Interface in Couchbase Mobile 2.0\" \/>\n<meta property=\"og:description\" content=\"Couchbase Mobile 2.0 supports a new query interface based on N1QL, Couchbase\u2019s declarative query language that extends SQL for JSON.\" \/>\n<meta property=\"og:url\" content=\"https:\/\/www.couchbase.com\/blog\/sql-for-json-query-interface-couchbase-mobile\/\" \/>\n<meta property=\"og:site_name\" content=\"The Couchbase Blog\" \/>\n<meta property=\"article:published_time\" content=\"2017-11-14T19:00:49+00:00\" \/>\n<meta property=\"article:modified_time\" content=\"2025-06-14T03:28:08+00:00\" \/>\n<meta property=\"og:image\" content=\"https:\/\/www.couchbase.com\/blog\/wp-content\/uploads\/sites\/1\/2017\/11\/feature_image.png\" \/>\n\t<meta property=\"og:image:width\" content=\"1716\" \/>\n\t<meta property=\"og:image:height\" content=\"842\" \/>\n\t<meta property=\"og:image:type\" content=\"image\/png\" \/>\n<meta name=\"author\" content=\"Priya Rajagopal, Senior Director, Product Management\" \/>\n<meta name=\"twitter:card\" content=\"summary_large_image\" \/>\n<meta name=\"twitter:creator\" content=\"@rajagp\" \/>\n<meta name=\"twitter:label1\" content=\"Written by\" \/>\n\t<meta name=\"twitter:data1\" content=\"Priya Rajagopal, Senior Director, Product Management\" \/>\n\t<meta name=\"twitter:label2\" content=\"Est. reading time\" \/>\n\t<meta name=\"twitter:data2\" content=\"13 minutes\" \/>\n<script type=\"application\/ld+json\" class=\"yoast-schema-graph\">{\"@context\":\"https:\/\/schema.org\",\"@graph\":[{\"@type\":\"Article\",\"@id\":\"https:\/\/www.couchbase.com\/blog\/sql-for-json-query-interface-couchbase-mobile\/#article\",\"isPartOf\":{\"@id\":\"https:\/\/www.couchbase.com\/blog\/sql-for-json-query-interface-couchbase-mobile\/\"},\"author\":{\"name\":\"Priya Rajagopal, Senior Director, Product Management\",\"@id\":\"https:\/\/www.couchbase.com\/blog\/#\/schema\/person\/c2da90e57717ee4970c48a87a131ac2c\"},\"headline\":\"Introducing the Query Interface in Couchbase Mobile 2.0\",\"datePublished\":\"2017-11-14T19:00:49+00:00\",\"dateModified\":\"2025-06-14T03:28:08+00:00\",\"mainEntityOfPage\":{\"@id\":\"https:\/\/www.couchbase.com\/blog\/sql-for-json-query-interface-couchbase-mobile\/\"},\"wordCount\":2179,\"commentCount\":8,\"publisher\":{\"@id\":\"https:\/\/www.couchbase.com\/blog\/#organization\"},\"image\":{\"@id\":\"https:\/\/www.couchbase.com\/blog\/sql-for-json-query-interface-couchbase-mobile\/#primaryimage\"},\"thumbnailUrl\":\"https:\/\/www.couchbase.com\/blog\/wp-content\/uploads\/sites\/1\/2017\/11\/feature_image.png\",\"keywords\":[\"API\",\"Couchbase Mobile 2.\",\"Index\",\"JSON\",\"sqlite\"],\"articleSection\":[\"Best Practices and Tutorials\",\"Couchbase Lite\",\"Couchbase Mobile\",\"Full-Text Search\",\"SQL++ \/ N1QL Query\"],\"inLanguage\":\"en-US\",\"potentialAction\":[{\"@type\":\"CommentAction\",\"name\":\"Comment\",\"target\":[\"https:\/\/www.couchbase.com\/blog\/sql-for-json-query-interface-couchbase-mobile\/#respond\"]}]},{\"@type\":\"WebPage\",\"@id\":\"https:\/\/www.couchbase.com\/blog\/sql-for-json-query-interface-couchbase-mobile\/\",\"url\":\"https:\/\/www.couchbase.com\/blog\/sql-for-json-query-interface-couchbase-mobile\/\",\"name\":\"Introducing the Query Interface in Couchbase Mobile 2.0\",\"isPartOf\":{\"@id\":\"https:\/\/www.couchbase.com\/blog\/#website\"},\"primaryImageOfPage\":{\"@id\":\"https:\/\/www.couchbase.com\/blog\/sql-for-json-query-interface-couchbase-mobile\/#primaryimage\"},\"image\":{\"@id\":\"https:\/\/www.couchbase.com\/blog\/sql-for-json-query-interface-couchbase-mobile\/#primaryimage\"},\"thumbnailUrl\":\"https:\/\/www.couchbase.com\/blog\/wp-content\/uploads\/sites\/1\/2017\/11\/feature_image.png\",\"datePublished\":\"2017-11-14T19:00:49+00:00\",\"dateModified\":\"2025-06-14T03:28:08+00:00\",\"description\":\"Couchbase Mobile 2.0 supports a new query interface based on N1QL, Couchbase\u2019s declarative query language that extends SQL for JSON.\",\"breadcrumb\":{\"@id\":\"https:\/\/www.couchbase.com\/blog\/sql-for-json-query-interface-couchbase-mobile\/#breadcrumb\"},\"inLanguage\":\"en-US\",\"potentialAction\":[{\"@type\":\"ReadAction\",\"target\":[\"https:\/\/www.couchbase.com\/blog\/sql-for-json-query-interface-couchbase-mobile\/\"]}]},{\"@type\":\"ImageObject\",\"inLanguage\":\"en-US\",\"@id\":\"https:\/\/www.couchbase.com\/blog\/sql-for-json-query-interface-couchbase-mobile\/#primaryimage\",\"url\":\"https:\/\/www.couchbase.com\/blog\/wp-content\/uploads\/sites\/1\/2017\/11\/feature_image.png\",\"contentUrl\":\"https:\/\/www.couchbase.com\/blog\/wp-content\/uploads\/sites\/1\/2017\/11\/feature_image.png\",\"width\":1716,\"height\":842,\"caption\":\"SQL for JSON Query\"},{\"@type\":\"BreadcrumbList\",\"@id\":\"https:\/\/www.couchbase.com\/blog\/sql-for-json-query-interface-couchbase-mobile\/#breadcrumb\",\"itemListElement\":[{\"@type\":\"ListItem\",\"position\":1,\"name\":\"Home\",\"item\":\"https:\/\/www.couchbase.com\/blog\/\"},{\"@type\":\"ListItem\",\"position\":2,\"name\":\"Introducing the Query Interface in Couchbase Mobile 2.0\"}]},{\"@type\":\"WebSite\",\"@id\":\"https:\/\/www.couchbase.com\/blog\/#website\",\"url\":\"https:\/\/www.couchbase.com\/blog\/\",\"name\":\"The Couchbase Blog\",\"description\":\"Couchbase, the NoSQL Database\",\"publisher\":{\"@id\":\"https:\/\/www.couchbase.com\/blog\/#organization\"},\"potentialAction\":[{\"@type\":\"SearchAction\",\"target\":{\"@type\":\"EntryPoint\",\"urlTemplate\":\"https:\/\/www.couchbase.com\/blog\/?s={search_term_string}\"},\"query-input\":{\"@type\":\"PropertyValueSpecification\",\"valueRequired\":true,\"valueName\":\"search_term_string\"}}],\"inLanguage\":\"en-US\"},{\"@type\":\"Organization\",\"@id\":\"https:\/\/www.couchbase.com\/blog\/#organization\",\"name\":\"The Couchbase Blog\",\"url\":\"https:\/\/www.couchbase.com\/blog\/\",\"logo\":{\"@type\":\"ImageObject\",\"inLanguage\":\"en-US\",\"@id\":\"https:\/\/www.couchbase.com\/blog\/#\/schema\/logo\/image\/\",\"url\":\"https:\/\/www.couchbase.com\/blog\/wp-content\/uploads\/2023\/04\/admin-logo.png\",\"contentUrl\":\"https:\/\/www.couchbase.com\/blog\/wp-content\/uploads\/2023\/04\/admin-logo.png\",\"width\":218,\"height\":34,\"caption\":\"The Couchbase Blog\"},\"image\":{\"@id\":\"https:\/\/www.couchbase.com\/blog\/#\/schema\/logo\/image\/\"}},{\"@type\":\"Person\",\"@id\":\"https:\/\/www.couchbase.com\/blog\/#\/schema\/person\/c2da90e57717ee4970c48a87a131ac2c\",\"name\":\"Priya Rajagopal, Senior Director, Product Management\",\"image\":{\"@type\":\"ImageObject\",\"inLanguage\":\"en-US\",\"@id\":\"https:\/\/www.couchbase.com\/blog\/#\/schema\/person\/image\/4b50a54778b979d8c345b036ab138734\",\"url\":\"https:\/\/secure.gravatar.com\/avatar\/acfb2349788955262cd069497a9e7bdb0e97c26326f2e55811e7c1174e9ef1be?s=96&d=mm&r=g\",\"contentUrl\":\"https:\/\/secure.gravatar.com\/avatar\/acfb2349788955262cd069497a9e7bdb0e97c26326f2e55811e7c1174e9ef1be?s=96&d=mm&r=g\",\"caption\":\"Priya Rajagopal, Senior Director, Product Management\"},\"description\":\"Priya Rajagopal is a Senior Director of Product Management at Couchbase responsible for developer platforms for the cloud and the edge. She has been professionally developing software for over 20 years in several technical and product leadership positions, with 10+ years focused on mobile technologies. As a TISPAN IPTV standards delegate, she was a key contributor to the IPTV standards specifications. She has 22 patents in the areas of networking and platform security.\",\"sameAs\":[\"https:\/\/x.com\/rajagp\"],\"url\":\"https:\/\/www.couchbase.com\/blog\/author\/priya-rajagopalcouchbase-com\/\"}]}<\/script>\n<!-- \/ Yoast SEO Premium plugin. -->","yoast_head_json":{"title":"Introducing the Query Interface in Couchbase Mobile 2.0","description":"Couchbase Mobile 2.0 supports a new query interface based on N1QL, Couchbase\u2019s declarative query language that extends SQL for JSON.","robots":{"index":"index","follow":"follow","max-snippet":"max-snippet:-1","max-image-preview":"max-image-preview:large","max-video-preview":"max-video-preview:-1"},"canonical":"https:\/\/www.couchbase.com\/blog\/sql-for-json-query-interface-couchbase-mobile\/","og_locale":"en_US","og_type":"article","og_title":"Introducing the Query Interface in Couchbase Mobile 2.0","og_description":"Couchbase Mobile 2.0 supports a new query interface based on N1QL, Couchbase\u2019s declarative query language that extends SQL for JSON.","og_url":"https:\/\/www.couchbase.com\/blog\/sql-for-json-query-interface-couchbase-mobile\/","og_site_name":"The Couchbase Blog","article_published_time":"2017-11-14T19:00:49+00:00","article_modified_time":"2025-06-14T03:28:08+00:00","og_image":[{"width":1716,"height":842,"url":"https:\/\/www.couchbase.com\/blog\/wp-content\/uploads\/sites\/1\/2017\/11\/feature_image.png","type":"image\/png"}],"author":"Priya Rajagopal, Senior Director, Product Management","twitter_card":"summary_large_image","twitter_creator":"@rajagp","twitter_misc":{"Written by":"Priya Rajagopal, Senior Director, Product Management","Est. reading time":"13 minutes"},"schema":{"@context":"https:\/\/schema.org","@graph":[{"@type":"Article","@id":"https:\/\/www.couchbase.com\/blog\/sql-for-json-query-interface-couchbase-mobile\/#article","isPartOf":{"@id":"https:\/\/www.couchbase.com\/blog\/sql-for-json-query-interface-couchbase-mobile\/"},"author":{"name":"Priya Rajagopal, Senior Director, Product Management","@id":"https:\/\/www.couchbase.com\/blog\/#\/schema\/person\/c2da90e57717ee4970c48a87a131ac2c"},"headline":"Introducing the Query Interface in Couchbase Mobile 2.0","datePublished":"2017-11-14T19:00:49+00:00","dateModified":"2025-06-14T03:28:08+00:00","mainEntityOfPage":{"@id":"https:\/\/www.couchbase.com\/blog\/sql-for-json-query-interface-couchbase-mobile\/"},"wordCount":2179,"commentCount":8,"publisher":{"@id":"https:\/\/www.couchbase.com\/blog\/#organization"},"image":{"@id":"https:\/\/www.couchbase.com\/blog\/sql-for-json-query-interface-couchbase-mobile\/#primaryimage"},"thumbnailUrl":"https:\/\/www.couchbase.com\/blog\/wp-content\/uploads\/sites\/1\/2017\/11\/feature_image.png","keywords":["API","Couchbase Mobile 2.","Index","JSON","sqlite"],"articleSection":["Best Practices and Tutorials","Couchbase Lite","Couchbase Mobile","Full-Text Search","SQL++ \/ N1QL Query"],"inLanguage":"en-US","potentialAction":[{"@type":"CommentAction","name":"Comment","target":["https:\/\/www.couchbase.com\/blog\/sql-for-json-query-interface-couchbase-mobile\/#respond"]}]},{"@type":"WebPage","@id":"https:\/\/www.couchbase.com\/blog\/sql-for-json-query-interface-couchbase-mobile\/","url":"https:\/\/www.couchbase.com\/blog\/sql-for-json-query-interface-couchbase-mobile\/","name":"Introducing the Query Interface in Couchbase Mobile 2.0","isPartOf":{"@id":"https:\/\/www.couchbase.com\/blog\/#website"},"primaryImageOfPage":{"@id":"https:\/\/www.couchbase.com\/blog\/sql-for-json-query-interface-couchbase-mobile\/#primaryimage"},"image":{"@id":"https:\/\/www.couchbase.com\/blog\/sql-for-json-query-interface-couchbase-mobile\/#primaryimage"},"thumbnailUrl":"https:\/\/www.couchbase.com\/blog\/wp-content\/uploads\/sites\/1\/2017\/11\/feature_image.png","datePublished":"2017-11-14T19:00:49+00:00","dateModified":"2025-06-14T03:28:08+00:00","description":"Couchbase Mobile 2.0 supports a new query interface based on N1QL, Couchbase\u2019s declarative query language that extends SQL for JSON.","breadcrumb":{"@id":"https:\/\/www.couchbase.com\/blog\/sql-for-json-query-interface-couchbase-mobile\/#breadcrumb"},"inLanguage":"en-US","potentialAction":[{"@type":"ReadAction","target":["https:\/\/www.couchbase.com\/blog\/sql-for-json-query-interface-couchbase-mobile\/"]}]},{"@type":"ImageObject","inLanguage":"en-US","@id":"https:\/\/www.couchbase.com\/blog\/sql-for-json-query-interface-couchbase-mobile\/#primaryimage","url":"https:\/\/www.couchbase.com\/blog\/wp-content\/uploads\/sites\/1\/2017\/11\/feature_image.png","contentUrl":"https:\/\/www.couchbase.com\/blog\/wp-content\/uploads\/sites\/1\/2017\/11\/feature_image.png","width":1716,"height":842,"caption":"SQL for JSON Query"},{"@type":"BreadcrumbList","@id":"https:\/\/www.couchbase.com\/blog\/sql-for-json-query-interface-couchbase-mobile\/#breadcrumb","itemListElement":[{"@type":"ListItem","position":1,"name":"Home","item":"https:\/\/www.couchbase.com\/blog\/"},{"@type":"ListItem","position":2,"name":"Introducing the Query Interface in Couchbase Mobile 2.0"}]},{"@type":"WebSite","@id":"https:\/\/www.couchbase.com\/blog\/#website","url":"https:\/\/www.couchbase.com\/blog\/","name":"The Couchbase Blog","description":"Couchbase, the NoSQL Database","publisher":{"@id":"https:\/\/www.couchbase.com\/blog\/#organization"},"potentialAction":[{"@type":"SearchAction","target":{"@type":"EntryPoint","urlTemplate":"https:\/\/www.couchbase.com\/blog\/?s={search_term_string}"},"query-input":{"@type":"PropertyValueSpecification","valueRequired":true,"valueName":"search_term_string"}}],"inLanguage":"en-US"},{"@type":"Organization","@id":"https:\/\/www.couchbase.com\/blog\/#organization","name":"The Couchbase Blog","url":"https:\/\/www.couchbase.com\/blog\/","logo":{"@type":"ImageObject","inLanguage":"en-US","@id":"https:\/\/www.couchbase.com\/blog\/#\/schema\/logo\/image\/","url":"https:\/\/www.couchbase.com\/blog\/wp-content\/uploads\/2023\/04\/admin-logo.png","contentUrl":"https:\/\/www.couchbase.com\/blog\/wp-content\/uploads\/2023\/04\/admin-logo.png","width":218,"height":34,"caption":"The Couchbase Blog"},"image":{"@id":"https:\/\/www.couchbase.com\/blog\/#\/schema\/logo\/image\/"}},{"@type":"Person","@id":"https:\/\/www.couchbase.com\/blog\/#\/schema\/person\/c2da90e57717ee4970c48a87a131ac2c","name":"Priya Rajagopal, Senior Director, Product Management","image":{"@type":"ImageObject","inLanguage":"en-US","@id":"https:\/\/www.couchbase.com\/blog\/#\/schema\/person\/image\/4b50a54778b979d8c345b036ab138734","url":"https:\/\/secure.gravatar.com\/avatar\/acfb2349788955262cd069497a9e7bdb0e97c26326f2e55811e7c1174e9ef1be?s=96&d=mm&r=g","contentUrl":"https:\/\/secure.gravatar.com\/avatar\/acfb2349788955262cd069497a9e7bdb0e97c26326f2e55811e7c1174e9ef1be?s=96&d=mm&r=g","caption":"Priya Rajagopal, Senior Director, Product Management"},"description":"Priya Rajagopal is a Senior Director of Product Management at Couchbase responsible for developer platforms for the cloud and the edge. She has been professionally developing software for over 20 years in several technical and product leadership positions, with 10+ years focused on mobile technologies. As a TISPAN IPTV standards delegate, she was a key contributor to the IPTV standards specifications. She has 22 patents in the areas of networking and platform security.","sameAs":["https:\/\/x.com\/rajagp"],"url":"https:\/\/www.couchbase.com\/blog\/author\/priya-rajagopalcouchbase-com\/"}]}},"authors":[{"term_id":8948,"user_id":1423,"is_guest":0,"slug":"priya-rajagopalcouchbase-com","display_name":"Priya Rajagopal, Senior Director, Product Management","avatar_url":"https:\/\/secure.gravatar.com\/avatar\/acfb2349788955262cd069497a9e7bdb0e97c26326f2e55811e7c1174e9ef1be?s=96&d=mm&r=g","author_category":"","last_name":"Rajagopal, Senior Director, Product Management","first_name":"Priya","job_title":"","user_url":"","description":"Priya Rajagopal is a Senior Director of Product Management at Couchbase responsible for developer platforms for the cloud and the edge. She has been professionally developing software for over 20 years in several technical and product leadership positions, with 10+ years focused on mobile technologies. As a TISPAN IPTV standards delegate, she was a key contributor to the IPTV standards specifications. She has 22 patents in the areas of networking and platform security."}],"_links":{"self":[{"href":"https:\/\/www.couchbase.com\/blog\/wp-json\/wp\/v2\/posts\/4187","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/www.couchbase.com\/blog\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/www.couchbase.com\/blog\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/www.couchbase.com\/blog\/wp-json\/wp\/v2\/users\/1423"}],"replies":[{"embeddable":true,"href":"https:\/\/www.couchbase.com\/blog\/wp-json\/wp\/v2\/comments?post=4187"}],"version-history":[{"count":0,"href":"https:\/\/www.couchbase.com\/blog\/wp-json\/wp\/v2\/posts\/4187\/revisions"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/www.couchbase.com\/blog\/wp-json\/wp\/v2\/media\/4188"}],"wp:attachment":[{"href":"https:\/\/www.couchbase.com\/blog\/wp-json\/wp\/v2\/media?parent=4187"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/www.couchbase.com\/blog\/wp-json\/wp\/v2\/categories?post=4187"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/www.couchbase.com\/blog\/wp-json\/wp\/v2\/tags?post=4187"},{"taxonomy":"author","embeddable":true,"href":"https:\/\/www.couchbase.com\/blog\/wp-json\/wp\/v2\/ppma_author?post=4187"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}