Fork me on GitHub

An interesting feature of CouchDB introduced in version 2.0 is the mango query server. This feature makes it much easier to query document without having to write views and mastering the map/reduce concepts.

Sohva supports sending such queries and also offers a DSL to make them easy to write.

Overview

The DSL lives in the mango package, thus start by importing it.

      import gnieh.sohva.mango._

    

Then you can start using it to write your query, starting with the find word.

      val query = find

    

You can filter the fields you are interested in using the fields clause

      val query = find fields ("title", "author", "date")

    

The selector part of the query comes after the where word where each field is represented by field("name").

      val query = find fields ("title", "author", "date") where field("tags").containsAll("post")

    

Selector expressions may be combined with && and ||.

Result of a query may be sorted using the sortBy word.

      val query = find fields ("title", "author", "date") where field("tags").containsAll("post") sortBy Asc("date")

    

Once you have your query built to your liking, you can run it against the database

      val result = db.find(query)

    

Constructors

To start a query using the DSL, use the find constructor which returns an empty request.

To start selecting on a field with the DSL, use the field constructors, which returns a SelectorBase with operators to build a complete selector.

To apply a selector on the subfields of a field, use the within constructor.

Combinators

$and combinator

      sel1 && sel2

    

is the json selector

      
        {
        
  
        "$and"
        :
         
        [
         
        sel
        1
        ,
         
        sel
        2
         
        ]
        

        }
        

      
    

$or combinator

      sel1 || sel2

    

is the json selector

      
        {
        
  
        "$or"
        :
         
        [
         
        sel
        1
        ,
         
        sel
        2
         
        ]
        

        }
        

      
    

$not combinator

      !sel

    

is the json selector

      
        {
        
  
        "$not"
        :
         
        sel
        

        }
        

      
    

$nor combinator

      !(sel1 || sel2)

    

is the json selector

      
        {
        
  
        "$nor"
        :
         
        [
         
        sel
        1
        ,
         
        sel
        2
         
        ]
        

        }
        

      
    

Conditions

$eq condition

      field("a") === 43

    

is the json selector

      
        {
        
  
        "a"
        :
         
        {
        
    
        "$eq"
        :
         
        43
        
  
        }
        

        }
        

      
    

$ne condition

      field("a") !== 4.3

    

is the json selector

      
        {
        
  
        "a"
        :
         
        {
        
    
        "$ne"
        :
         
        4.3
        
  
        }
        

        }
        

      
    

$lt condition

      field("a") < 122

    

is the json selector

      
        {
        
  
        "a"
        :
         
        {
        
    
        "$lt"
        :
         
        122
        
  
        }
        

        }
        

      
    

$lte condition

      field("a") <= 122

    

is the json selector

      
        {
        
  
        "a"
        :
         
        {
        
    
        "$lte"
        :
         
        122
        
  
        }
        

        }
        

      
    

$gt condition

      field("a") > 233

    

is the json selector

      
        {
        
  
        "a"
        :
         
        {
        
    
        "$gt"
        :
         
        233
        
  
        }
        

        }
        

      
    

$gte condition

      field("a") >= 233

    

is the json selector

      
        {
        
  
        "a"
        :
         
        {
        
    
        "$gte"
        :
         
        233
        
  
        }
        

        }
        

      
    

$exists condition

      field("a").exists

    

is the json selector

      
        {
        
  
        "a"
        :
         
        {
        
    
        "$exists"
        :
         
        true
        
  
        }
        

        }
        


      
    
      field("a").doesNotExist

    

is the json selector

      
        {
        
  
        "a"
        :
         
        {
        
    
        "$exists"
        :
         
        false
        
  
        }
        

        }
        

      
    

$type condition

      field("a").hasType("string")

    

is the json selector

      
        {
        
  
        "a"
        :
         
        {
        
    
        "$type"
        :
         
        "string"
        
  
        }
        

        }
        

      
    

$in condition

      field("a") in Vector("a", "b", "c")

    

is the json selector

      
        {
        
  
        "a"
        :
         
        {
        
    
        "$in"
        :
         
        [
         
        "a"
        ,
         
        "b"
        ,
         
        "c"
         
        ]
        
  
        }
        

        }
        

      
    

$nin condition

      field("a") notIn Vector("a", "b", "c")

    

is the json selector

      
        {
        
  
        "a"
        :
         
        {
        
    
        "$nin"
        :
         
        [
         
        "a"
        ,
         
        "b"
        ,
         
        "c"
         
        ]
        
  
        }
        

        }
        

      
    

$size condition

      field("a").hasSize(34)

    

is the json selector

      
        {
        
  
        "a"
        :
         
        {
        
    
        "$size"
        :
         
        34
        
  
        }
        

        }
        

      
    

$mod condition

      field("a") % 4 === 3

    

is the json selector

      
        {
        
  
        "a"
        :
         
        {
        
    
        "$mod"
        :
         
        [
         
        4
        ,
         
        3
         
        ]
        
  
        }
        

        }
        

      
    

$regex condition

      field("a").matches("[a-zA-Z_][a-zA-Z0-9_]*")

    

is the json selector

      
        {
        
  
        "a"
        :
         
        {
        
    
        "$regex"
        :
         
        "[a-zA-Z_][a-zA-Z0-9_]*"
        
  
        }
        

        }
        

      
    

$all condition

      field("a").containsAll("a", "b", "c")

    

is the json selector

      
        {
        
  
        "a"
        :
         
        {
        
    
        "$all"
        :
         
        [
         
        "a"
        ,
         
        "b"
        ,
         
        "c"
         
        ]
        
  
        }
        

        }
        

      
    

$elemMatch condition

      field("a").contains(sel)

    

is the json selector

      
        {
        
  
        "a"
        :
         
        {
        
    
        "$elemMatch"
        :
         
        sel
        
  
        }
        

      
    

Query

Define the selector

      val query = find where sel

    

defines a query with the given selector.

Select fields

      val query = find fields ("a", "b", "c")

    

returns only the given fields.

Sort result

      val query = q sortBy (Asc("a"), Desc("b"))

    

sorts the result of query q ascending by field a and then descending by field b.

Limit the result

      val query = q limit 54

    

returns only the 54 first result of query q.

Skip some results

      val query = q skip 43

    

skips the 43 first results of query q.

Using a specific index

      val query = q use ("design", "idx")
// or
val query = q use "design"

    

transforms query q to use the specified index

Resetting some query elements

      val query = q without sort

    

is the query q without its sort elements.