QuerySyntax
Provides chainable objects to build Chef search queries as well as a method to share, re-use and extend queries.
Installation
Add this line to your application's Gemfile:
gem 'query_syntax'
And then execute:
$ bundle
Or install it yourself as:
$ gem install query_syntax
** NOTE ** Updated, as of 1.0.4 only compatible with newer chefs with filter_results
Usage
QuerySyntax::Query provides bang and non-bang methods for and, or, not, where which determine whether we are modifying the current object or whether we are returning a new object. In most cases though, QuerySyntax will return the QuerySyntax object so that we can chain at will.
The following methods are most likely to be used :
.where!(hash)
An AND-ed hash of criteria to search for within a single (scope). If multiple values are provided for a single key from subsequent where! or where calls, then the value is converted to an array of values which are OR-ed.
Also notice that, as long as we chain where!, we are contribution criteria to the same scope.
Query.where!(a:1).to_s
> a:1
Query.where!(a:1, b:1).to_s
> (a:1 AND b:1)
Query.where!(a:1, b:1).where!(a:2,b:2).to_s
> ((a:1 OR a:2) AND (b:1 OR b:2))
.and!(hash)
Very similar to where!, we add additional criteria which we AND to the query. Unlike where!, however, and! generates a new (scope).
If and! is specified without a hash, we decide that the entire left most portion of the statement is to be made it's own composite scope.
Query.where!(a:1, b:1).where!(a:2,b:2).to_s
> ((a:1 OR a:2) AND (b:1 OR b:2))
Query.where!(a:0,b:1).where!(a:2,b:2).and!(a:2,b:2).to_s
> ((a:0 OR a:2) AND (b:1 OR b:2)) AND (a:2 AND b:2)
.or!(hash) and .not!(hash)
function exactly like .and, however with a different operator than AND.
.push(object)
may be used to begin with a baseline and build on top of it.
Examples
# Create a baseline query
Chef::Search.add_query("base")
Chef::Search.base.
where!(chef_environment:"production").to_s
> chef_environment:production
# Create peers query
Chef::Search.add_query("peers")
Chef::Search.peers.push(Chef::Search.base).
where!(roles:"load_balancer").to_s
> chef_environment:production AND roles:load_balancer
# Update the baseline
Chef::Search.base.
not!(tags:"maintenance").to_s
> chef_environment:production NOT tags:maintenance
Chef::Search.peers.to_s
> (chef_environment:production NOT tags:maintenance) AND roles:load_balancer
# Return an updated peers query for single use, notice there's no ! symbol
Chef::Search.peers.where(roles:"shard1").to_s
> (chef_environment:production NOT tags:maintenance) AND roles:load_balancer AND roles:shard1
Chef::Search.base.to_s
# Unchanged
> chef_environment:production NOT tags:maintenance
Chef::Search.peers.to_s
# Unchanged
> (chef_environment:production NOT tags:maintenance) AND roles:load_balancer
# Perform a search
Chef::Search.peers.search.map { |item| item.node_name }
> [node,node,node]
# Perform a partial search
# notice we automatically ensure values are Arrays when they are strings
Chef::Search.peers.partial(
keys:{chef_environment:"chef_environment",hostname:["hostname"]
)
> [{chef_environment:"production", hostname:"host1"}]
Contributing
- Fork it ( https://github.com/[my-github-username]/query_syntax/fork )
- Create your feature branch (
git checkout -b my-new-feature
) - Commit your changes (
git commit -am 'Add some feature'
) - Push to the branch (
git push origin my-new-feature
) - Create a new Pull Request