{"id":6189,"date":"2018-12-21T01:07:09","date_gmt":"2018-12-21T09:07:09","guid":{"rendered":"https:\/\/www.couchbase.com\/blog\/?p=6189"},"modified":"2025-06-13T20:28:50","modified_gmt":"2025-06-14T03:28:50","slug":"searching-json-comparing-text-search-in-couchbase-and-mongodb","status":"publish","type":"post","link":"https:\/\/www.couchbase.com\/blog\/searching-json-comparing-text-search-in-couchbase-and-mongodb\/","title":{"rendered":"Searching JSON: compare text search in Couchbase and MongoDB."},"content":{"rendered":"<blockquote><p>&#8220;Apps without search is like Google homepage without the search bar.&#8221;<\/p><\/blockquote>\n<p><img loading=\"lazy\" decoding=\"async\" class=\"aligncenter wp-image-6199\" src=\"https:\/\/www.couchbase.com\/blog\/wp-content\/uploads\/2018\/12\/Screen-Shot-2018-12-21-at-1.03.47-AM-300x161.png\" alt=\"\" width=\"732\" height=\"393\" \/><\/p>\n<p>It&#8217;s hard to design an app without a good search.\u00a0 These days, it&#8217;s also hard to find a database without a built-in search. MySQL to NoSQL, Sybase to Couchbase, every database has text search support &#8212; built-in like Couchbase or via integration to Elastic &#8212; as is the case in Cassandra. Unlike SQL, text search functionality isn&#8217;t standardized. Every application needs best of the breed search, but not every database provides the same text search functionality. It&#8217;s important to understand the available feature, performance of each text search implementation and choose what fits your application need. After motivating text search, you&#8217;ll learn about the text search features you&#8217;d need for an effective, compare and contrast those features in MongoDB and Couchbase with examples.<\/p>\n<h5>Let&#8217;s look at the application level search requirements.<\/h5>\n<ol>\n<li>\n<h5>Exact Search:\u00a0(WHERE item_id = &#8220;ABC482&#8221;)<\/h5>\n<\/li>\n<li>\n<h5>Range Search:\u00a0(WHERE item_type = &#8220;shoes&#8221; and size = 6 and price between 49.99 and 99.99)<\/h5>\n<\/li>\n<li>\n<h5>String search:<\/h5>\n<ul>\n<li>\n<h5>(WHERE lower(name) LIKE &#8220;%joe%&#8221;)<\/h5>\n<\/li>\n<li>\n<h5>(WHERE lower(name) LIKE &#8220;%joe%&#8221; AND state = &#8220;CA&#8221;)<\/h5>\n<\/li>\n<\/ul>\n<\/li>\n<li>\n<h5>Document search:<\/h5>\n<ul>\n<li>\n<h5>Find joe in any field within the JSON document<\/h5>\n<\/li>\n<li>\n<h5>Find documents matching phone number (408-956-2444) in any format (+1 (408) 956-2444, +1 510.956.2444, (408) 956 2444)<\/h5>\n<\/li>\n<\/ul>\n<\/li>\n<li>\n<h5>Complex search: (WHERE\u00a0lower(title) LIKE &#8220;%dictator%&#8221; and lower(actor) LIKE &#8220;%chaplin&#8221; and year &lt; 1950)<\/h5>\n<\/li>\n<\/ol>\n<h5>Range searches in cases (1) and (2) can be handled with typical B-Tree indexes efficiently. The data is well organized by the full data you&#8217;re searching for.\u00a0 When you start to look for the word fragment &#8220;joe&#8221; or match phone numbers with various patterns in a larger document, B-Tree based indexes suffer. Simple <a href=\"https:\/\/dzone.com\/articles\/more-than-like-efficient-json-search-with-couchbas\">tokenizations<\/a> and using B-Tree based indexes can help in simple cases.\u00a0 You need new approaches to your real-world search cases.<\/h5>\n<h5>The appendix section of this blog has more details on how the inverted tree indexes are organized and why they&#8217;re used for the enterprise search in <a href=\"https:\/\/lucene.apache.org\/\">Lucene<\/a> and <a href=\"https:\/\/blevesearch.com\/\">Bleve<\/a>.\u00a0 Bleve powers the Couchbse full-text search.\u00a0 MongoDB uses B-Tree based indexes even for text search.<\/h5>\n<h5>Let&#8217;s now focus on the text search support in MongoDB and Couchbase.<\/h5>\n<h5>Dataset I&#8217;ve used is from\u00a0<a href=\"https:\/\/github.com\/jdorfman\/awesome-json-datasets#movies\">https:\/\/github.com\/jdorfman\/awesome-json-datasets#movies<\/a><\/h5>\n<h5><span style=\"font-weight: 400\">MongoDB: <\/span><a href=\"https:\/\/docs.mongodb.com\/manual\/text-search\/\"><span style=\"font-weight: 400\">https:\/\/docs.mongodb.com\/manual\/text-search\/<\/span><\/a><\/h5>\n<h5><span style=\"font-weight: 400\">Couchbase: <\/span><a href=\"https:\/\/docs.couchbase.com\/server\/6.0\/fts\/full-text-intro.html\"><span style=\"font-weight: 400\">https:\/\/docs.couchbase.com\/server\/6.0\/fts\/full-text-intro.html<\/span><\/a><\/h5>\n<h5><span style=\"font-weight: 400\"><span style=\"color: #008000\"><strong>MongoDB Text Search Overview:<\/strong>\u00a0<\/span> Create and query text search index on strings of MongoDB documents.\u00a0 The index seems to be simple B-tree indexes with additional layers for the built-in analyzer.\u00a0 This comes with a lot of sizing and performance issues we&#8217;ll discuss further.\u00a0 The text search index is tightly integrated into the MongoDB\u00a0database infrastructure and its query API.\u00a0<\/span><\/h5>\n<h5><span style=\"font-weight: 400\">MongoDB provides text indexes to support text search queries only on strings. Its text indexes can include only fields whose value is a string or an array of string elements.\u00a0<\/span><span style=\"font-weight: 400\">A collection can only have one text search index, but that index can cover multiple fields.<\/span><\/h5>\n<h5><span style=\"font-weight: 400\"><span style=\"color: #ff0000\"><strong>Couchbase FTS (Full-Text Search) Overview:<\/strong> <\/span>Full-Text Search provides extensive capabilities for natural-language querying.\u00a0Bleve, implemented as an inverted index, powers the Couchbase full-text index.\u00a0 The index is deployed as one of the services and can be deployed on any of the nodes in the cluster.<\/span><\/h5>\n<p>&nbsp;<\/p>\n<table>\n<tbody>\n<tr>\n<td>\n<h5><\/h5>\n<\/td>\n<td>\n<h4><span style=\"color: #008000\"><b>MongoDB<\/b><\/span><\/h4>\n<\/td>\n<td>\n<h4><span style=\"color: #ff0000\"><b>Couchbase<\/b><\/span><\/h4>\n<\/td>\n<\/tr>\n<tr>\n<td>\n<h5><strong>Name<\/strong><\/h5>\n<\/td>\n<td>\n<h5>Text search &#8211; 4.x<\/h5>\n<\/td>\n<td>\n<h5>Full-Text Search (FTS) &#8211; 6.x.<\/h5>\n<\/td>\n<\/tr>\n<tr>\n<td>\n<h5><strong>Functionality<\/strong><\/h5>\n<\/td>\n<td>\n<h5>Simple text search to index string fields and search for a string in one or more string fields only.\u00a0 Uses its <strong>B-Tree indexes<\/strong> for the text search index.<\/h5>\n<h5>Search on the whole composite string and cannot separate the specific fields.<\/h5>\n<\/td>\n<td>\n<h5>Full-text search to find anything in your data. Supports all JSON data types (string, numeric, boolean, date\/time); query supports complex boolean expressions, fuzzy expressions on any type of fields.\u00a0 Uses the <strong>inverted index<\/strong>\u00a0for the text search index.<\/h5>\n<\/td>\n<\/tr>\n<tr>\n<td>\n<h5><b>Installation<\/b><\/h5>\n<\/td>\n<td>\n<h5>Text search: Available with MongoDB installation. No separate installation option.<\/h5>\n<\/td>\n<td>\n<h5>Available with Couchbase installation. Can be installed with other services (data, query, index, etc) or installed separately on distinct search nodes.<\/h5>\n<\/td>\n<\/tr>\n<tr>\n<td>\n<h5><b>Index creation on a single field<\/b><\/h5>\n<\/td>\n<td>\n<h5>db.films.createIndex({ title: &#8220;text&#8221; });<\/h5>\n<\/td>\n<td>\n<h5 class=\"p1\"><span class=\"s1\">curl -u Administrator:password -XPUT<span class=\"Apple-converted-space\">\u00a0 <\/span>https:\/\/localhost:8094\/api\/index\/films_title<span class=\"Apple-converted-space\">\u00a0 <\/span>-H &#8216;cache-control: no-cache&#8217;<span class=\"Apple-converted-space\">\u00a0 <\/span>-H &#8216;content-type: application\/json&#8217;<span class=\"Apple-converted-space\">\u00a0 <\/span>-d &#8216;{ &#8220;name&#8221;: &#8220;films_title&#8221;, &#8220;type&#8221;: &#8220;fulltext-index&#8221;, &#8220;params&#8221;: { &#8220;mapping&#8221;: { &#8220;default_field&#8221;: &#8220;title&#8221; } }, &#8220;sourceType&#8221;: &#8220;couchbase&#8221;, &#8220;sourceName&#8221;: &#8220;films&#8221; }&#8217;<\/span><\/h5>\n<\/td>\n<\/tr>\n<tr>\n<td>\n<h5><b>Index creation on multiple fields<\/b><\/h5>\n<\/td>\n<td>\n<h5>db.films.createIndex({ title: &#8220;text&#8221;, genres: &#8220;text&#8221;});<\/h5>\n<h5>Before you can create this index, you\u2019ve to drop the previous index. <span style=\"color: #0000ff\">There can be only one text index on a collection<\/span>. You need its name, which you get by: db.films.getIndexes() or specify the name while creating the index.<\/h5>\n<h5>db.films.dropIndex(&#8220;title_text&#8221;);<\/h5>\n<\/td>\n<td>\n<h5>You can create as multiple indexes on a bucket (or keyspace) without restriction.<\/h5>\n<h5 class=\"p1\"><span class=\"s1\">curl -u Administrator:password -XPUT https:\/\/localhost:8094\/api\/index\/films_title_genres -H &#8216;cache-control: no-cache&#8217; -H &#8216;content-type: application\/json&#8217; -d &#8216;{ &#8220;name&#8221;: &#8220;films_title_genres&#8221;, &#8220;type&#8221;: &#8220;fulltext-index&#8221;, &#8220;params&#8221;: {<span class=\"Apple-converted-space\">\u00a0 \u00a0 <\/span>&#8220;mapping&#8221;: { &#8220;types&#8221;: { &#8220;genres&#8221;: { &#8220;enabled&#8221;: true, &#8220;dynamic&#8221;: false }, &#8220;title&#8221;: { &#8220;enabled&#8221;: true, &#8220;dynamic&#8221;: false }}}}, &#8220;sourceType&#8221;: &#8220;couchbase&#8221;, &#8220;sourceName&#8221;: &#8220;films&#8221; }&#8217;<\/span><\/h5>\n<\/td>\n<\/tr>\n<tr>\n<td>\n<h5><b>Using weights<\/b><\/h5>\n<\/td>\n<td>\n<h5>db.films.createIndex({ title: &#8220;text&#8221;, genres: &#8220;text&#8221;}, {weights:{title: 25}, name : &#8220;txt_title_genres&#8221;});<b><\/b><\/h5>\n<\/td>\n<td>\n<h5>Done dynamically via boosting using the ^ mofidier.<\/h5>\n<h5 id=\"jsonQueryCurlContent\" class=\"ng-binding\">curl -XPOST -H &#8220;Content-Type: application\/json&#8221; \\ https:\/\/172.23.120.38:8094\/api\/index\/films_title_genres\/query \\ -d &#8216;{ &#8220;explain&#8221;: true, &#8220;fields&#8221;: [ &#8220;*&#8221; ], &#8220;highlight&#8221;: {}, &#8220;query&#8221;: { &#8220;query&#8221;: &#8220;title:charlie^40 genres:comedy^5&#8221; } }&#8217;<\/h5>\n<\/td>\n<\/tr>\n<tr>\n<td>\n<h5><b>Language option<\/b><\/h5>\n<\/td>\n<td>\n<h5>Default language is English. Pass in a parameter to change that.<\/h5>\n<h5>db.films.createIndex({ title: &#8220;text&#8221;}, { default_language: &#8220;french&#8221; });<\/h5>\n<\/td>\n<td>\n<h5>Analyzers are available in 24 languages.\u00a0 You can change is while creating the index by changing the following parameter.<\/h5>\n<h5 id=\"index_def_preview\" class=\"ng-binding\">&#8220;default_analyzer&#8221;: &#8220;fr&#8221;,<\/h5>\n<\/td>\n<\/tr>\n<tr>\n<td>\n<h5><b>Case insensitive text index<\/b><\/h5>\n<\/td>\n<td>\n<h5>Case insensitive by default. Extended to new languages.<\/h5>\n<\/td>\n<td>\n<h5>Case insensitive by default.<\/h5>\n<\/td>\n<\/tr>\n<tr>\n<td>\n<h5><b>diacritic insensitive<\/b><\/h5>\n<\/td>\n<td>\n<h5>With version 3, the text index is diacritic insensitive.<\/h5>\n<\/td>\n<td>\n<h5>Yes.\u00a0 Automatically enabled in the appropriate analyzer (e.g. French)<\/h5>\n<\/td>\n<\/tr>\n<tr>\n<td>\n<h5><b>Delimiters<\/b><\/h5>\n<\/td>\n<td>\n<h5>Dash, Hyphen, Pattern_Syntax, Quotation_Mark, Terminal_Punctuation, and White_Space<\/h5>\n<\/td>\n<td>\n<h5>Each work is analyzed based on the language and analyzer specification.<\/h5>\n<\/td>\n<\/tr>\n<tr>\n<td>\n<h5><b>Languages<\/b><\/h5>\n<\/td>\n<td>\n<h5>15 languages:<\/h5>\n<h5 class=\"p1\"><span class=\"s1\">danish, dutch, english, finnish, french, german, hungarian, italian, norwegian, portuguese, romanian, russian, spanish, swedish, turkish<\/span><\/h5>\n<\/td>\n<td>Token filters are supported for the following languages.<\/p>\n<p class=\"p1\"><span class=\"s1\">Arabic, Catalan, Chinese , Japanese , Korean, Kurdish, Danish, German, Greek, English, Spanish (Castilian), Basque, Persian, Finnish, French, Gaelic, Spanish (Galician), Hindi, Hungarian, Armenian, Indonesian, Italian, Dutch, Norwegian, Portuguese, Romanian, Russian, Swedish, Turkish<\/span><\/p>\n<\/td>\n<\/tr>\n<tr>\n<td>\n<h5><b>Type of Index<\/b><\/h5>\n<\/td>\n<td>\n<h5>Simple B-Tree index containing on entry for each stemmed word in each document.<\/h5>\n<h5>text indexes can be large. They contain one index entry for each unique post-stemmed word in each indexed field for each document inserted.<\/h5>\n<\/td>\n<td>\n<h5>Inverted index. \u00a0One entry per stemmed word in the WHOLE index (per index partition). \u00a0So, the index sizes are significantly smaller index. The more humongous the data set is, Couchbase FTS index is that much more efficient compared to MongoDB text index.<\/h5>\n<\/td>\n<\/tr>\n<tr>\n<td>\n<h5><b>Index creation effect on INSERTS.<\/b><\/h5>\n<\/td>\n<td>\n<h5>Will negatively affect the INSERT rate.<\/h5>\n<\/td>\n<td>\n<h5>INSERT\/UPSERT rates will remain unaffected<\/h5>\n<\/td>\n<\/tr>\n<tr>\n<td>\n<h5><b>Index Maintenance<\/b><\/h5>\n<\/td>\n<td>\n<h5>Synchronously Maintained.<\/h5>\n<\/td>\n<td>\n<h5>Asynchronously maintained. \u00a0Queries can specify the staleness using the consistency parameter.<\/h5>\n<\/td>\n<\/tr>\n<tr>\n<td>\n<h5><b>phrase queries<\/b><\/h5>\n<\/td>\n<td>\n<h5>Supported, but slow.<\/h5>\n<h5>Phrase searches slow since the text index does not include the required metadata about the proximity of words in the documents. As a result, phrase queries will run much more effectively when the entire collection fits in RAM.<\/h5>\n<\/td>\n<td>Supported and fast.<\/p>\n<p>Include the term vectors during index creation.<\/td>\n<\/tr>\n<tr>\n<td>\n<h5><b>Text search <\/b><\/h5>\n<\/td>\n<td>\n<h5>db.films.find({$text: {$search: \u201ccharlie chaplin\u201d}})<\/h5>\n<h5>This find all the documents that contain charlie OR chaplin. \u00a0Having both charlie and chaplin will get higher score. Since there can be only ONE text index per collection, this query uses that index irrespective of the field it indexes. \u00a0So, it\u2019s important to decide which of the fields should be in the index.<\/h5>\n<\/td>\n<td>\n<pre id=\"jsonQueryCurlContent\" class=\"ng-binding\">Very Flexible text search. \r\n\r\ncurl -XPOST -H \"Content-Type: application\/json\" \\\r\nhttps:\/\/172.23.120.38:8094\/api\/index\/films_title_genres\/query \\\r\n-d '{\r\n  \"explain\": true,\r\n  \"fields\": [\r\n    \"*\"\r\n  ],\r\n  \"highlight\": {},\r\n  \"query\": {\r\n    \"query\": \"charlie chaplin\"\r\n  }\r\n}'<\/pre>\n<\/td>\n<\/tr>\n<tr>\n<td>\n<h5>Exact phrase search<\/h5>\n<\/td>\n<td>\n<h5>db.films.find({$text: {$search: \u201c\\\u201dcharlie chaplin\\\u201d\u201d}})<\/h5>\n<\/td>\n<td>\n<pre id=\"jsonQueryCurlContent\" class=\"ng-binding\">curl -XPOST -H \"Content-Type: application\/json\" \\\r\nhttps:\/\/172.23.120.38:8094\/api\/index\/films_title_genres\/query \\\r\n-d '{\r\n  \"explain\": true,\r\n  \"fields\": [\r\n    \"*\"\r\n  ],\r\n  \"highlight\": {},\r\n  \"query\": {\r\n    \"query\": \"\\\"charlie chaplin\\\"\"\r\n  }\r\n}'<\/pre>\n<\/td>\n<\/tr>\n<tr>\n<td><b>Exact Exclusion<\/b><\/td>\n<td>db.films.find({$text: {$search: \u201ccharlie -chaplin\u201d}});<\/p>\n<p>All the movie with \u201ccharlie\u201d, but without \u201cchaplin\u201d.<\/td>\n<td>\n<pre id=\"jsonQueryCurlContent\" class=\"ng-binding\">curl -XPOST -H \"Content-Type: application\/json\" \\\r\nhttps:\/\/172.23.120.38:8094\/api\/index\/films_title_genres\/query \\\r\n-d '{\r\n  \"explain\": true,\r\n  \"fields\": [\r\n    \"*\"\r\n  ],\r\n  \"highlight\": {},\r\n  \"query\": {\r\n    \"query\": \"charlie -chaplin\"\r\n  }\r\n}'<\/pre>\n<\/td>\n<\/tr>\n<tr>\n<td><strong>Results order.<\/strong><\/td>\n<td>\n<h5>Unordered by default.<\/h5>\n<h5>Project and sort by score when you need it.<\/h5>\n<h5>db.films.find({$text: {$search: \u201ccharlie chaplin\u201d}},\u00a0{score: {$meta: \u201csearchscore\u201d}}).sort({$meta: \u201csearchscore\u201d})<\/h5>\n<\/td>\n<td>Ordered by score (descending) by default. Can order by any field or meta data.\u00a0 This sorts by title and score (descending)<\/p>\n<pre id=\"jsonQueryCurlContent\" class=\"ng-binding\">curl -XPOST -H \"Content-Type: application\/json\" \\\r\nhttps:\/\/172.23.120.38:8094\/api\/index\/films_title_genres\/query \\\r\n-d '{\r\n  \"explain\": true,\r\n  \"fields\": [\r\n    \"*\"\r\n  ],\r\n  \"highlight\": {},\r\n  \"sort\":[\"title\", \"-_score\"]\r\n  \"query\": {\r\n    \"query\": \"charlie -chaplin\"\r\n  }\r\n}'<\/pre>\n<\/td>\n<\/tr>\n<tr>\n<td><b>Specific language search<\/b><\/td>\n<td>\n<h5>db.articles.find(<\/h5>\n<h5>\u00a0\u00a0{ $text: { $search: &#8220;leche&#8221;, $language: &#8220;es&#8221; } }<\/h5>\n<h5>)<\/h5>\n<\/td>\n<td>The language analyzer will have determined the characteristics of the index and query.<\/td>\n<\/tr>\n<tr>\n<td><b>Case insensitive search<\/b><\/td>\n<td>\n<h5>db.film.find( { $text: { $search: &#8220;Lawrence&#8221;, $caseSensitive: true } } )<b><\/b><\/h5>\n<p>&nbsp;<\/td>\n<td>Determined by the analyer.\u00a0 Use the to_lower token filter so all the searches are case inensitive.\u00a0 See more at:\u00a0https:\/\/docs.couchbase.com\/server\/6.0\/fts\/fts-using-analyzers.html<\/td>\n<\/tr>\n<tr>\n<td><b>Limiting the return resultset.<\/b><\/td>\n<td>\n<h5>db.films.find({$text: {$search: \u201ccharlie chaplin\u201d}},{score: {$meta:\u00a0 \u201csearchscore\u201d}}).sort({$meta: \u201csearchscore\u201d}).limit(10)<\/h5>\n<\/td>\n<td>Supports the equivalant of LIMIT and SKIP in SQL using &#8220;size&#8221; and &#8220;from&#8221; parameters respectively.<\/p>\n<pre id=\"jsonQueryCurlContent\" class=\"ng-binding\">curl -XPOST -H \"Content-Type: application\/json\" \\\r\nhttps:\/\/172.23.120.38:8094\/api\/index\/films_title_genres\/query \\\r\n-d '{\r\n  \"explain\": true,\r\n  \"fields\": [\r\n    \"*\"\r\n  ],\r\n  \"highlight\": {},\r\n  \"query\": {\r\n    \"query\": \"charlie chaplin\"\r\n  }, \r\n  \"size\":10,\r\n  \"from\":40\r\n}'<\/pre>\n<\/td>\n<\/tr>\n<tr>\n<td><b>Complex sorting<\/b><\/td>\n<td>\n<h5>db.films.find({$text: {$search: \u201ccharlie chaplin\u201d}},<\/h5>\n<h5>{score: {$meta: \u201csearchscore\u201d}}).sort({year : 1, $meta: \u201csearchscore\u201d}).limit(10)<\/h5>\n<\/td>\n<td>Ordered by score (descending) by default. Can order by any field or meta data.\u00a0 This sorts by title (ascending), year (descending) and score (descending)<\/p>\n<pre id=\"jsonQueryCurlContent\" class=\"ng-binding\">curl -XPOST -H \"Content-Type: application\/json\" \\\r\nhttps:\/\/172.23.120.38:8094\/api\/index\/films_title_genres\/query \\\r\n-d '{\r\n  \"explain\": true,\r\n  \"fields\": [\r\n    \"*\"\r\n  ],\r\n  \"highlight\": {},\r\n  \"sort\":[\"title\", \"-year\", \"-_score\"]\r\n  \"query\": {\r\n    \"query\": \"charlie -chaplin\"\r\n  }\r\n}'<\/pre>\n<\/td>\n<\/tr>\n<tr>\n<td><b>Complex query<\/b><\/td>\n<td>\n<h5>Use the aggregation framework. \u00a0$text search can be used in an aggregation framework with some restrictions.<\/h5>\n<h5>db.articles.aggregate(<br \/>\n[<br \/>\n{ $match: { $text: { $search: &#8220;charlie chaplin&#8221; } } },<br \/>\n{ $project: { title: 1, _id: 0, score: { $meta: &#8220;searchscore&#8221; } } },<br \/>\n{ $match: { score: { $gt: 5.0 } } }<br \/>\n]<br \/>\n)<\/h5>\n<ul>\n<li>Limitations: <a href=\"https:\/\/docs.mongodb.com\/manual\/tutorial\/text-search-in-aggregation\/\">https:\/\/docs.mongodb.com\/manual\/tutorial\/text-search-in-aggregation\/<\/a><\/li>\n<\/ul>\n<\/td>\n<td>As you&#8217;ve seen so far, FTS query itself is pretty sophisticated. In addition, FTS supports facets for simple grouping and counting.\u00a0<a href=\"https:\/\/docs.couchbase.com\/server\/6.0\/fts\/fts-response-object-schema.html\">https:\/\/docs.couchbase.com\/server\/6.0\/fts\/fts-response-object-schema.html<\/a><\/p>\n<p>In the upcoming release, N1QL (SQL for JSON) will use the FTS index for search predicates.<\/p>\n<p>&nbsp;<\/p>\n<pre class=\"\">SELECT state, sum(sales)\r\nFROM store_sales s\r\nWHERE search(s.title, \"lego\", \"fts_title\")\r\nGROUP BY state<\/pre>\n<\/td>\n<\/tr>\n<tr>\n<td><b>Full document index<\/b><\/td>\n<td>Does not support full document indexing.\u00a0 All the string fields will have to be specified in the createIndex call.<\/p>\n<h5>db.films.createIndex({ title: &#8220;text&#8221;, generes: &#8220;text&#8221;, cast: &#8220;text&#8221;, year: &#8220;text&#8221;});<b><\/b><\/h5>\n<p>&nbsp;<\/td>\n<td>By default, it supports indexing the full document, automatically recognizes the type of the\u00a0 field and indexes them accordingly.<\/td>\n<\/tr>\n<tr>\n<td><b>Query Types<\/b><\/td>\n<td>\n<h5>Basic search, must have, must not have.<\/h5>\n<\/td>\n<td>\n<h5>Match, Match Phrase, Doc ID, and Prefix queries<\/h5>\n<h5>Conjunction, Disjunction, and Boolean field queries<\/h5>\n<h5>Numeric Range and Date Range queries<\/h5>\n<h5>Geospatial queries<\/h5>\n<h5>Query String queries, which employ a special syntax to express the details of each query (see Query String Query for information)<\/h5>\n<\/td>\n<\/tr>\n<tr>\n<td><b>Available analyzers<\/b><\/td>\n<td>Built-in analyzers only.<\/td>\n<td>Built-in and customizable analyzers. See more at:\u00a0<a href=\"https:\/\/docs.couchbase.com\/server\/6.0\/fts\/fts-using-analyzers.html#character-filters\/token-filters\">https:\/\/docs.couchbase.com\/server\/6.0\/fts\/fts-using-analyzers.html#character-filters\/token-filters<\/a><b><br \/>\n<\/b><\/td>\n<\/tr>\n<tr>\n<td>\n<h5><b>Create and search via UI<\/b><\/h5>\n<\/td>\n<td>\n<h5>Not in the base product.<\/h5>\n<\/td>\n<td>\n<h5>Built into Console<\/h5>\n<\/td>\n<\/tr>\n<tr>\n<td><b>REST API<\/b><\/td>\n<td>\n<h5>Unavailable.<\/h5>\n<\/td>\n<td><b>Available.<\/b><\/p>\n<p><a href=\"https:\/\/docs.couchbase.com\/server\/6.0\/fts\/fts-searching-with-the-rest-api.html\"><b>https:\/\/docs.couchbase.com\/server\/6.0\/fts\/fts-searching-with-the-rest-api.html<\/b><\/a><\/p>\n<p><b>https:\/\/docs.couchbase.com\/server\/6.0\/rest-api\/rest-fts.html<\/b><\/td>\n<\/tr>\n<tr>\n<td>\n<h5><b>SDK<\/b><\/h5>\n<\/td>\n<td>\n<h5>Text search is built-into with most Mongo SDKs.\u00a0 \u00a0E.g.\u00a0https:\/\/mongodb.github.io\/mongo-java-driver\/<\/h5>\n<\/td>\n<td>\n<h5><a href=\"https:\/\/docs.couchbase.com\/java-sdk\/2.7\/full-text-searching-with-sdk.html\">https:\/\/docs.couchbase.com\/java-sdk\/2.7\/full-text-searching-with-sdk.html<\/a><\/h5>\n<\/td>\n<\/tr>\n<tr>\n<td><b>Datatypes supported<\/b><\/td>\n<td><b>String only.\u00a0 No other datatype is supported.<\/b><\/td>\n<td><b>All JSON data types and date-times.<\/b><\/p>\n<p><b>String, numeric, boolean, datetime, object and arrays. <\/b><\/p>\n<p><b>GEOPOINT for nearest-neighbor queries.\u00a0 \u00a0See :\u00a0<\/b><a href=\"https:\/\/docs.couchbase.com\/server\/6.0\/fts\/fts-geospatial-queries.html\">https:\/\/docs.couchbase.com\/server\/6.0\/fts\/fts-geospatial-queries.html<\/a><\/td>\n<\/tr>\n<tr>\n<td><strong>Term Vectors.<\/strong><\/td>\n<td>Unsupported.<\/td>\n<td>Available. \u00a0 Term vectors are very useful in phrase search.<\/td>\n<\/tr>\n<tr>\n<td><strong>Faceting<\/strong><\/td>\n<td>Unsupported<\/td>\n<td>\n<h5>Term Facet<\/h5>\n<h5>Numeric Range Facet<\/h5>\n<h5>Date Range Facet<\/h5>\n<h5><a href=\"https:\/\/docs.couchbase.com\/server\/6.0\/fts\/fts-response-object-schema.html\">https:\/\/docs.couchbase.com\/server\/6.0\/fts\/fts-response-object-schema.html<\/a><\/h5>\n<\/td>\n<\/tr>\n<tr>\n<td><strong>Advanced AND queries (conjuncts)<\/strong><\/td>\n<td>Unsupported.<\/td>\n<td>\n<h5>curl -u Administrator:password -XPOST -H &#8220;Content-Type: application\/json&#8221; https:\/\/172.23.120.38:8094\/api\/index\/filmsearch\/query -d &#8216;{<\/h5>\n<h5>\u00a0&#8220;explain&#8221;: true,<\/h5>\n<h5>\u00a0&#8220;fields&#8221;: [<\/h5>\n<h5>\u00a0\u00a0\u00a0&#8220;*&#8221;<\/h5>\n<h5>\u00a0],<\/h5>\n<h5>\u00a0&#8220;highlight&#8221;: {},<\/h5>\n<h5>\u00a0&#8220;query&#8221;: {<\/h5>\n<h5>\u00a0\u00a0\u00a0&#8220;conjuncts&#8221;:[ { &#8220;field&#8221;:&#8221;title&#8221;, &#8220;match&#8221;:&#8221;kid&#8221;}, {&#8220;field&#8221;:&#8221;cast&#8221;, &#8220;match&#8221;:&#8221;chaplin&#8221;}]<\/h5>\n<h5>\u00a0}<\/h5>\n<h5>}&#8217;<\/h5>\n<\/td>\n<\/tr>\n<tr>\n<td><strong>Advanced OR queries (disjuncts)<\/strong><\/td>\n<td>Unsupported.<\/td>\n<td>\n<h5>curl -u Administrator:password -XPOST -H &#8220;Content-Type: application\/json&#8221; https:\/\/172.23.120.38:8094\/api\/index\/filmsearch\/query -d &#8216;{<\/h5>\n<h5>\u00a0&#8220;explain&#8221;: true,<\/h5>\n<h5>\u00a0&#8220;fields&#8221;: [<\/h5>\n<h5>\u00a0\u00a0\u00a0&#8220;*&#8221;<\/h5>\n<h5>\u00a0],<\/h5>\n<h5>\u00a0&#8220;highlight&#8221;: {},<\/h5>\n<h5>\u00a0&#8220;query&#8221;: {<\/h5>\n<h5>\u00a0\u00a0\u00a0&#8220;disjuncts&#8221;:[ { &#8220;field&#8221;:&#8221;title&#8221;, &#8220;match&#8221;:&#8221;kid&#8221;}, {&#8220;field&#8221;:&#8221;cast&#8221;, &#8220;match&#8221;:&#8221;chaplin&#8221;}]<\/h5>\n<h5>\u00a0}<\/h5>\n<h5>}&#8217;<\/h5>\n<\/td>\n<\/tr>\n<tr>\n<td>\u00a0<strong>Date range queries<\/strong><\/td>\n<td>Unsupported.<\/p>\n<p>Needs post processing, which could affect the performance.<\/td>\n<td>\u00a0Supported with FTS.<\/p>\n<h5>{<br \/>\n&#8220;start&#8221;: &#8220;2001-10-09T10:20:30-08:00&#8221;,<br \/>\n&#8220;end&#8221;: &#8220;2016-10-31&#8221;,<br \/>\n&#8220;inclusive_start&#8221;: false,<br \/>\n&#8220;inclusive_end&#8221;: false,<br \/>\n&#8220;field&#8221;: &#8220;review_date&#8221;<br \/>\n}<\/h5>\n<\/td>\n<\/tr>\n<tr>\n<td><strong>Numerical range queries<\/strong><\/td>\n<td>\u00a0Unsupported.<\/td>\n<td>\u00a0curl -u Administrator:password -XPOST -H &#8220;Content-Type: application\/json&#8221; https:\/\/172.23.120.38:8094\/api\/index\/filmsearch\/query -d &#8216;{<br \/>\n&#8220;explain&#8221;: true,<br \/>\n&#8220;fields&#8221;: [<br \/>\n&#8220;*&#8221;<br \/>\n],<br \/>\n&#8220;highlight&#8221;: {},<br \/>\n&#8220;query&#8221;: {<br \/>\n&#8220;field&#8221;:&#8221;year&#8221;, &#8220;min&#8221;:1999, &#8220;max&#8221;:1999, &#8220;inclusive_min&#8221;: true, &#8220;inclusive_max&#8221;:true<br \/>\n}<br \/>\n}&#8217;<\/td>\n<\/tr>\n<\/tbody>\n<\/table>\n<h5><strong><span style=\"color: #0000ff\">Performance:<\/span><\/strong><\/h5>\n<p>While an elaborate performance comparison is still pending, we did a quick comparison with 1 million documents from wikipedia. Here&#8217;s what we saw:<\/p>\n<p><strong>Index Sizes.<\/strong><\/p>\n<table dir=\"ltr\" border=\"1\" cellspacing=\"0\" cellpadding=\"0\">\n<colgroup>\n<col width=\"158\" \/>\n<col width=\"237\" \/>\n<col width=\"100\" \/><\/colgroup>\n<tbody>\n<tr>\n<td><\/td>\n<td>Couchbase (6.0)<\/td>\n<td>MongoDB (4.x)<\/td>\n<\/tr>\n<tr>\n<td>Indexing Size<\/td>\n<td>1 GB (scorch)<\/td>\n<td>1.6 GB<\/td>\n<\/tr>\n<tr>\n<td>Indexing Time<\/td>\n<td>46 sec<\/td>\n<td>7.5 min<\/td>\n<\/tr>\n<\/tbody>\n<\/table>\n<p><strong>Search Query Throughput (queries per second):<\/strong><\/p>\n<p class=\"p1\"><span class=\"s1\"><span class=\"Apple-converted-space\">\u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 <strong>\u00a0Couchbase<\/strong><\/span><strong><span class=\"Apple-converted-space\">\u00a0 \u00a0 \u00a0\u00a0<\/span>Mongodb<\/strong><\/span><\/p>\n<p class=\"p1\"><span class=\"s1\">High fequency terms<span class=\"Apple-converted-space\">\u00a0 \u00a0 \u00a0 \u00a0 \u00a0<\/span>395<span class=\"Apple-converted-space\">\u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0<\/span>79<span class=\"Apple-converted-space\">\u00a0 \u00a0<\/span><\/span><\/p>\n<p class=\"p1\"><span class=\"s1\">Med<span class=\"Apple-converted-space\">\u00a0 <\/span>fequency terms <span class=\"Apple-converted-space\">\u00a0 \u00a0 \u00a0 \u00a0<\/span>6396 <span class=\"Apple-converted-space\">\u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0\u00a0<\/span>201<\/span><\/p>\n<p class=\"p1\"><span class=\"s1\">Low<span class=\"Apple-converted-space\">\u00a0 <\/span>fequency terms<span class=\"Apple-converted-space\">\u00a0 \u00a0 \u00a0 \u00a0<\/span>24600 <span class=\"Apple-converted-space\">\u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0\u00a0<\/span>643<\/span><\/p>\n<p class=\"p1\"><span class=\"s1\">High or High<span class=\"Apple-converted-space\">\u00a0 <\/span>terms<span class=\"Apple-converted-space\">\u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0\u00a0<\/span>145<span class=\"Apple-converted-space\">\u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0\u00a0<\/span>82<span class=\"Apple-converted-space\">\u00a0 \u00a0<\/span><\/span><\/p>\n<p class=\"p1\"><span class=\"s1\">High or Med <span class=\"Apple-converted-space\">\u00a0 <\/span>terms<span class=\"Apple-converted-space\">\u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0\u00a0<\/span>258<span class=\"Apple-converted-space\">\u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0\u00a0<\/span>78\u00a0 \u00a0<\/span><\/p>\n<p class=\"p1\"><span class=\"s1\">Phrase search<span class=\"Apple-converted-space\">\u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0<\/span>107<span class=\"Apple-converted-space\">\u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0 \u00a0<\/span>50<span class=\"Apple-converted-space\">\u00a0 \u00a0 \u00a0<\/span><\/span><\/p>\n<h5><span style=\"color: #0000ff\"><strong>Summary:<\/strong><\/span><\/h5>\n<p>MongoDB provides simple string-search index and APIs to do string search.\u00a0 The B-tree index it creates for string search also be quite huge. Text search, it is not.<\/p>\n<p>Couchbase text index is based on inverted index and is a full text index with a significantly more of features and better performance.<\/p>\n<p>&nbsp;<\/p>\n<p><strong><span style=\"color: #0000ff\">Why Inverted Index for search index?<\/span><\/strong><\/p>\n<h6>Simple exact and range searches can be powered by <a href=\"https:\/\/en.wikipedia.org\/wiki\/B-tree\">B-Tree<\/a> like indexes for an efficient scan. Text searches, however, have wider requirement of stemming, stopwords, analyzers, etc.\u00a0 This requires not only a different indexing approach but also pre-index filtering, custom analysis tools, language specific\u00a0stemming and case insensitivities.<\/h6>\n<h6>Search index can be created using traditional B-TREE.\u00a0 But, unlike a B-tree indexes on scalar values,\u00a0 text index will have multiple index entries for each document.\u00a0 A text index on this document alone could have up to 12 entries: 8 for cast names, one for genres, two for the title after removing the stop word (in) and the year. Larger documents and document counts will increase the size of the text index exponentially.<\/h6>\n<pre class=\"theme:github tab-size:2 whitespace-before:2 whitespace-after:2 lang:js decode:true\">  {\r\n      \"cast\": [\r\n        \"Whoopi Goldberg\",\r\n        \"Ted Danson\",\r\n        \"Will Smith\",\r\n        \"Nia Long\"\r\n      ],\r\n      \"genres\": [\r\n        \"Comedy\"\r\n      ],\r\n      \"title\": \"Made in America\",\r\n      \"year\": 1993\r\n    }\r\n  }<\/pre>\n<h6><\/h6>\n<h6><strong>Solution:<\/strong> Here comes the inverted tree.\u00a0 The inverted tree has the data (search term) at the top (root) and has various document keys in which the term exists at the bottom, making the structure look like an inverted tree.\u00a0 Popular text indexes in <a href=\"https:\/\/lucene.apache.org\/\">Lucene<\/a>, <a href=\"https:\/\/blevesearch.com\/\">Bleve<\/a> are all implemented as inverted indexes.<\/h6>\n<p><img loading=\"lazy\" decoding=\"async\" class=\"wp-image-6191 alignleft\" src=\"https:\/\/www.couchbase.com\/blog\/wp-content\/uploads\/2018\/12\/Screen-Shot-2018-12-19-at-9.30.00-PM-300x150.png\" alt=\"\" width=\"556\" height=\"278\" srcset=\"https:\/\/www.couchbase.com\/blog\/wp-content\/uploads\/sites\/1\/2018\/12\/Screen-Shot-2018-12-19-at-9.30.00-PM-300x150.png 300w, https:\/\/www.couchbase.com\/blog\/wp-content\/uploads\/sites\/1\/2018\/12\/Screen-Shot-2018-12-19-at-9.30.00-PM-1024x511.png 1024w, https:\/\/www.couchbase.com\/blog\/wp-content\/uploads\/sites\/1\/2018\/12\/Screen-Shot-2018-12-19-at-9.30.00-PM-768x383.png 768w, https:\/\/www.couchbase.com\/blog\/wp-content\/uploads\/sites\/1\/2018\/12\/Screen-Shot-2018-12-19-at-9.30.00-PM-20x10.png 20w, https:\/\/www.couchbase.com\/blog\/wp-content\/uploads\/sites\/1\/2018\/12\/Screen-Shot-2018-12-19-at-9.30.00-PM-1320x659.png 1320w, https:\/\/www.couchbase.com\/blog\/wp-content\/uploads\/sites\/1\/2018\/12\/Screen-Shot-2018-12-19-at-9.30.00-PM.png 1354w\" sizes=\"auto, (max-width: 556px) 100vw, 556px\" \/><\/p>\n<p><img loading=\"lazy\" decoding=\"async\" class=\"\" src=\"https:\/\/encrypted-tbn0.gstatic.com\/images?q=tbn:ANd9GcS9mgPR7VdKR2Jtxp0oh0-DumD82wsaOAQ08ZIVUcUJnBfvibB15A\" alt=\"Image result for inverted tree\" width=\"240\" height=\"321\" \/><\/p>\n<p>&nbsp;<\/p>\n","protected":false},"excerpt":{"rendered":"<p>&#8220;Apps without search is like Google homepage without the search bar.&#8221; It&#8217;s hard to design an app without a good search.\u00a0 These days, it&#8217;s also hard to find a database without a built-in search. MySQL to NoSQL, Sybase to Couchbase, [&hellip;]<\/p>\n","protected":false},"author":55,"featured_media":6192,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"_acf_changed":false,"inline_featured_image":false,"footnotes":""},"categories":[1814,1816,2165,1812],"tags":[1292,1309],"ppma_author":[8929],"class_list":["post-6189","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-application-design","category-couchbase-server","category-full-text-search","category-n1ql-query","tag-elasticsearch","tag-mongodb"],"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>Compare text search in Couchbase &amp; MongoDB- The Couchbase Blog<\/title>\n<meta name=\"description\" content=\"Learn more about the text search features for an effective, compare and contrast those available features in MongoDB and Couchbase with examples.\" \/>\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\/searching-json-comparing-text-search-in-couchbase-and-mongodb\/\" \/>\n<meta property=\"og:locale\" content=\"en_US\" \/>\n<meta property=\"og:type\" content=\"article\" \/>\n<meta property=\"og:title\" content=\"Searching JSON: compare text search in Couchbase and MongoDB.\" \/>\n<meta property=\"og:description\" content=\"Learn more about the text search features for an effective, compare and contrast those available features in MongoDB and Couchbase with examples.\" \/>\n<meta property=\"og:url\" content=\"https:\/\/www.couchbase.com\/blog\/searching-json-comparing-text-search-in-couchbase-and-mongodb\/\" \/>\n<meta property=\"og:site_name\" content=\"The Couchbase Blog\" \/>\n<meta property=\"article:published_time\" content=\"2018-12-21T09:07:09+00:00\" \/>\n<meta property=\"article:modified_time\" content=\"2025-06-14T03:28:50+00:00\" \/>\n<meta property=\"og:image\" content=\"https:\/\/www.couchbase.com\/blog\/wp-content\/uploads\/sites\/1\/2018\/12\/Glacier-Gardens-replace-1170x731.jpg\" \/>\n\t<meta property=\"og:image:width\" content=\"1170\" \/>\n\t<meta property=\"og:image:height\" content=\"731\" \/>\n\t<meta property=\"og:image:type\" content=\"image\/jpeg\" \/>\n<meta name=\"author\" content=\"Keshav Murthy\" \/>\n<meta name=\"twitter:card\" content=\"summary_large_image\" \/>\n<meta name=\"twitter:creator\" content=\"@rkeshavmurthy\" \/>\n<meta name=\"twitter:label1\" content=\"Written by\" \/>\n\t<meta name=\"twitter:data1\" content=\"Keshav Murthy\" \/>\n\t<meta name=\"twitter:label2\" content=\"Est. reading time\" \/>\n\t<meta name=\"twitter:data2\" content=\"11 minutes\" \/>\n<script type=\"application\/ld+json\" class=\"yoast-schema-graph\">{\"@context\":\"https:\/\/schema.org\",\"@graph\":[{\"@type\":\"Article\",\"@id\":\"https:\/\/www.couchbase.com\/blog\/searching-json-comparing-text-search-in-couchbase-and-mongodb\/#article\",\"isPartOf\":{\"@id\":\"https:\/\/www.couchbase.com\/blog\/searching-json-comparing-text-search-in-couchbase-and-mongodb\/\"},\"author\":{\"name\":\"Keshav Murthy\",\"@id\":\"https:\/\/www.couchbase.com\/blog\/#\/schema\/person\/c261644262bf98e146372fe647682636\"},\"headline\":\"Searching JSON: compare text search in Couchbase and MongoDB.\",\"datePublished\":\"2018-12-21T09:07:09+00:00\",\"dateModified\":\"2025-06-14T03:28:50+00:00\",\"mainEntityOfPage\":{\"@id\":\"https:\/\/www.couchbase.com\/blog\/searching-json-comparing-text-search-in-couchbase-and-mongodb\/\"},\"wordCount\":2235,\"commentCount\":0,\"publisher\":{\"@id\":\"https:\/\/www.couchbase.com\/blog\/#organization\"},\"image\":{\"@id\":\"https:\/\/www.couchbase.com\/blog\/searching-json-comparing-text-search-in-couchbase-and-mongodb\/#primaryimage\"},\"thumbnailUrl\":\"https:\/\/www.couchbase.com\/blog\/wp-content\/uploads\/sites\/1\/2018\/12\/Glacier-Gardens-replace-1170x731.jpg\",\"keywords\":[\"elasticsearch\",\"mongodb\"],\"articleSection\":[\"Application Design\",\"Couchbase Server\",\"Full-Text Search\",\"SQL++ \/ N1QL Query\"],\"inLanguage\":\"en-US\",\"potentialAction\":[{\"@type\":\"CommentAction\",\"name\":\"Comment\",\"target\":[\"https:\/\/www.couchbase.com\/blog\/searching-json-comparing-text-search-in-couchbase-and-mongodb\/#respond\"]}]},{\"@type\":\"WebPage\",\"@id\":\"https:\/\/www.couchbase.com\/blog\/searching-json-comparing-text-search-in-couchbase-and-mongodb\/\",\"url\":\"https:\/\/www.couchbase.com\/blog\/searching-json-comparing-text-search-in-couchbase-and-mongodb\/\",\"name\":\"Compare text search in Couchbase & MongoDB- The Couchbase Blog\",\"isPartOf\":{\"@id\":\"https:\/\/www.couchbase.com\/blog\/#website\"},\"primaryImageOfPage\":{\"@id\":\"https:\/\/www.couchbase.com\/blog\/searching-json-comparing-text-search-in-couchbase-and-mongodb\/#primaryimage\"},\"image\":{\"@id\":\"https:\/\/www.couchbase.com\/blog\/searching-json-comparing-text-search-in-couchbase-and-mongodb\/#primaryimage\"},\"thumbnailUrl\":\"https:\/\/www.couchbase.com\/blog\/wp-content\/uploads\/sites\/1\/2018\/12\/Glacier-Gardens-replace-1170x731.jpg\",\"datePublished\":\"2018-12-21T09:07:09+00:00\",\"dateModified\":\"2025-06-14T03:28:50+00:00\",\"description\":\"Learn more about the text search features for an effective, compare and contrast those available features in MongoDB and Couchbase with examples.\",\"breadcrumb\":{\"@id\":\"https:\/\/www.couchbase.com\/blog\/searching-json-comparing-text-search-in-couchbase-and-mongodb\/#breadcrumb\"},\"inLanguage\":\"en-US\",\"potentialAction\":[{\"@type\":\"ReadAction\",\"target\":[\"https:\/\/www.couchbase.com\/blog\/searching-json-comparing-text-search-in-couchbase-and-mongodb\/\"]}]},{\"@type\":\"ImageObject\",\"inLanguage\":\"en-US\",\"@id\":\"https:\/\/www.couchbase.com\/blog\/searching-json-comparing-text-search-in-couchbase-and-mongodb\/#primaryimage\",\"url\":\"https:\/\/www.couchbase.com\/blog\/wp-content\/uploads\/sites\/1\/2018\/12\/Glacier-Gardens-replace-1170x731.jpg\",\"contentUrl\":\"https:\/\/www.couchbase.com\/blog\/wp-content\/uploads\/sites\/1\/2018\/12\/Glacier-Gardens-replace-1170x731.jpg\",\"width\":1170,\"height\":731},{\"@type\":\"BreadcrumbList\",\"@id\":\"https:\/\/www.couchbase.com\/blog\/searching-json-comparing-text-search-in-couchbase-and-mongodb\/#breadcrumb\",\"itemListElement\":[{\"@type\":\"ListItem\",\"position\":1,\"name\":\"Home\",\"item\":\"https:\/\/www.couchbase.com\/blog\/\"},{\"@type\":\"ListItem\",\"position\":2,\"name\":\"Searching JSON: compare text search in Couchbase and MongoDB.\"}]},{\"@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\/c261644262bf98e146372fe647682636\",\"name\":\"Keshav Murthy\",\"image\":{\"@type\":\"ImageObject\",\"inLanguage\":\"en-US\",\"@id\":\"https:\/\/www.couchbase.com\/blog\/#\/schema\/person\/image\/4e51d72fc07c662aa791316deafffac4\",\"url\":\"https:\/\/secure.gravatar.com\/avatar\/af74df754db27152971d0aed2f323ead5a1f9fe5afd0209af91e12e784451224?s=96&d=mm&r=g\",\"contentUrl\":\"https:\/\/secure.gravatar.com\/avatar\/af74df754db27152971d0aed2f323ead5a1f9fe5afd0209af91e12e784451224?s=96&d=mm&r=g\",\"caption\":\"Keshav Murthy\"},\"description\":\"Keshav Murthy is a Vice President at Couchbase R&amp;D. Previously, he was at MapR, IBM, Informix, Sybase, with more than 20 years of experience in database design &amp; development. He lead the SQL and NoSQL R&amp;D team at IBM Informix. He has received two President's Club awards at Couchbase, two Outstanding Technical Achievement Awards at IBM. Keshav has a bachelor's degree in Computer Science and Engineering from the University of Mysore, India, holds eleven US patents and has four US patents pending.\",\"sameAs\":[\"https:\/\/blog.planetnosql.com\/\",\"https:\/\/x.com\/rkeshavmurthy\"],\"url\":\"https:\/\/www.couchbase.com\/blog\/author\/keshav-murthy\/\"}]}<\/script>\n<!-- \/ Yoast SEO Premium plugin. -->","yoast_head_json":{"title":"Compare text search in Couchbase & MongoDB- The Couchbase Blog","description":"Learn more about the text search features for an effective, compare and contrast those available features in MongoDB and Couchbase with examples.","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\/searching-json-comparing-text-search-in-couchbase-and-mongodb\/","og_locale":"en_US","og_type":"article","og_title":"Searching JSON: compare text search in Couchbase and MongoDB.","og_description":"Learn more about the text search features for an effective, compare and contrast those available features in MongoDB and Couchbase with examples.","og_url":"https:\/\/www.couchbase.com\/blog\/searching-json-comparing-text-search-in-couchbase-and-mongodb\/","og_site_name":"The Couchbase Blog","article_published_time":"2018-12-21T09:07:09+00:00","article_modified_time":"2025-06-14T03:28:50+00:00","og_image":[{"width":1170,"height":731,"url":"https:\/\/www.couchbase.com\/blog\/wp-content\/uploads\/sites\/1\/2018\/12\/Glacier-Gardens-replace-1170x731.jpg","type":"image\/jpeg"}],"author":"Keshav Murthy","twitter_card":"summary_large_image","twitter_creator":"@rkeshavmurthy","twitter_misc":{"Written by":"Keshav Murthy","Est. reading time":"11 minutes"},"schema":{"@context":"https:\/\/schema.org","@graph":[{"@type":"Article","@id":"https:\/\/www.couchbase.com\/blog\/searching-json-comparing-text-search-in-couchbase-and-mongodb\/#article","isPartOf":{"@id":"https:\/\/www.couchbase.com\/blog\/searching-json-comparing-text-search-in-couchbase-and-mongodb\/"},"author":{"name":"Keshav Murthy","@id":"https:\/\/www.couchbase.com\/blog\/#\/schema\/person\/c261644262bf98e146372fe647682636"},"headline":"Searching JSON: compare text search in Couchbase and MongoDB.","datePublished":"2018-12-21T09:07:09+00:00","dateModified":"2025-06-14T03:28:50+00:00","mainEntityOfPage":{"@id":"https:\/\/www.couchbase.com\/blog\/searching-json-comparing-text-search-in-couchbase-and-mongodb\/"},"wordCount":2235,"commentCount":0,"publisher":{"@id":"https:\/\/www.couchbase.com\/blog\/#organization"},"image":{"@id":"https:\/\/www.couchbase.com\/blog\/searching-json-comparing-text-search-in-couchbase-and-mongodb\/#primaryimage"},"thumbnailUrl":"https:\/\/www.couchbase.com\/blog\/wp-content\/uploads\/sites\/1\/2018\/12\/Glacier-Gardens-replace-1170x731.jpg","keywords":["elasticsearch","mongodb"],"articleSection":["Application Design","Couchbase Server","Full-Text Search","SQL++ \/ N1QL Query"],"inLanguage":"en-US","potentialAction":[{"@type":"CommentAction","name":"Comment","target":["https:\/\/www.couchbase.com\/blog\/searching-json-comparing-text-search-in-couchbase-and-mongodb\/#respond"]}]},{"@type":"WebPage","@id":"https:\/\/www.couchbase.com\/blog\/searching-json-comparing-text-search-in-couchbase-and-mongodb\/","url":"https:\/\/www.couchbase.com\/blog\/searching-json-comparing-text-search-in-couchbase-and-mongodb\/","name":"Compare text search in Couchbase & MongoDB- The Couchbase Blog","isPartOf":{"@id":"https:\/\/www.couchbase.com\/blog\/#website"},"primaryImageOfPage":{"@id":"https:\/\/www.couchbase.com\/blog\/searching-json-comparing-text-search-in-couchbase-and-mongodb\/#primaryimage"},"image":{"@id":"https:\/\/www.couchbase.com\/blog\/searching-json-comparing-text-search-in-couchbase-and-mongodb\/#primaryimage"},"thumbnailUrl":"https:\/\/www.couchbase.com\/blog\/wp-content\/uploads\/sites\/1\/2018\/12\/Glacier-Gardens-replace-1170x731.jpg","datePublished":"2018-12-21T09:07:09+00:00","dateModified":"2025-06-14T03:28:50+00:00","description":"Learn more about the text search features for an effective, compare and contrast those available features in MongoDB and Couchbase with examples.","breadcrumb":{"@id":"https:\/\/www.couchbase.com\/blog\/searching-json-comparing-text-search-in-couchbase-and-mongodb\/#breadcrumb"},"inLanguage":"en-US","potentialAction":[{"@type":"ReadAction","target":["https:\/\/www.couchbase.com\/blog\/searching-json-comparing-text-search-in-couchbase-and-mongodb\/"]}]},{"@type":"ImageObject","inLanguage":"en-US","@id":"https:\/\/www.couchbase.com\/blog\/searching-json-comparing-text-search-in-couchbase-and-mongodb\/#primaryimage","url":"https:\/\/www.couchbase.com\/blog\/wp-content\/uploads\/sites\/1\/2018\/12\/Glacier-Gardens-replace-1170x731.jpg","contentUrl":"https:\/\/www.couchbase.com\/blog\/wp-content\/uploads\/sites\/1\/2018\/12\/Glacier-Gardens-replace-1170x731.jpg","width":1170,"height":731},{"@type":"BreadcrumbList","@id":"https:\/\/www.couchbase.com\/blog\/searching-json-comparing-text-search-in-couchbase-and-mongodb\/#breadcrumb","itemListElement":[{"@type":"ListItem","position":1,"name":"Home","item":"https:\/\/www.couchbase.com\/blog\/"},{"@type":"ListItem","position":2,"name":"Searching JSON: compare text search in Couchbase and MongoDB."}]},{"@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\/c261644262bf98e146372fe647682636","name":"Keshav Murthy","image":{"@type":"ImageObject","inLanguage":"en-US","@id":"https:\/\/www.couchbase.com\/blog\/#\/schema\/person\/image\/4e51d72fc07c662aa791316deafffac4","url":"https:\/\/secure.gravatar.com\/avatar\/af74df754db27152971d0aed2f323ead5a1f9fe5afd0209af91e12e784451224?s=96&d=mm&r=g","contentUrl":"https:\/\/secure.gravatar.com\/avatar\/af74df754db27152971d0aed2f323ead5a1f9fe5afd0209af91e12e784451224?s=96&d=mm&r=g","caption":"Keshav Murthy"},"description":"Keshav Murthy is a Vice President at Couchbase R&amp;D. Previously, he was at MapR, IBM, Informix, Sybase, with more than 20 years of experience in database design &amp; development. He lead the SQL and NoSQL R&amp;D team at IBM Informix. He has received two President's Club awards at Couchbase, two Outstanding Technical Achievement Awards at IBM. Keshav has a bachelor's degree in Computer Science and Engineering from the University of Mysore, India, holds eleven US patents and has four US patents pending.","sameAs":["https:\/\/blog.planetnosql.com\/","https:\/\/x.com\/rkeshavmurthy"],"url":"https:\/\/www.couchbase.com\/blog\/author\/keshav-murthy\/"}]}},"authors":[{"term_id":8929,"user_id":55,"is_guest":0,"slug":"keshav-murthy","display_name":"Keshav Murthy","avatar_url":"https:\/\/secure.gravatar.com\/avatar\/af74df754db27152971d0aed2f323ead5a1f9fe5afd0209af91e12e784451224?s=96&d=mm&r=g","author_category":"","last_name":"Murthy","first_name":"Keshav","job_title":"","user_url":"https:\/\/blog.planetnosql.com\/","description":"Keshav Murthy is a Vice President at Couchbase R&amp;D. Previously, he was at MapR, IBM, Informix, Sybase, with more than 20 years of experience in database design &amp; development. He lead the SQL and NoSQL R&amp;D team at IBM Informix. He has received two President's Club awards at Couchbase, two Outstanding Technical Achievement Awards at IBM. Keshav has a bachelor's degree in Computer Science and Engineering from the University of Mysore, India,  holds ten US patents and has three US patents pending."}],"_links":{"self":[{"href":"https:\/\/www.couchbase.com\/blog\/wp-json\/wp\/v2\/posts\/6189","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\/55"}],"replies":[{"embeddable":true,"href":"https:\/\/www.couchbase.com\/blog\/wp-json\/wp\/v2\/comments?post=6189"}],"version-history":[{"count":0,"href":"https:\/\/www.couchbase.com\/blog\/wp-json\/wp\/v2\/posts\/6189\/revisions"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/www.couchbase.com\/blog\/wp-json\/wp\/v2\/media\/6192"}],"wp:attachment":[{"href":"https:\/\/www.couchbase.com\/blog\/wp-json\/wp\/v2\/media?parent=6189"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/www.couchbase.com\/blog\/wp-json\/wp\/v2\/categories?post=6189"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/www.couchbase.com\/blog\/wp-json\/wp\/v2\/tags?post=6189"},{"taxonomy":"author","embeddable":true,"href":"https:\/\/www.couchbase.com\/blog\/wp-json\/wp\/v2\/ppma_author?post=6189"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}