Skip to content

Commit

Permalink
Merge pull request #110 from theablefew/feature/match_in_where
Browse files Browse the repository at this point in the history
Support match in where, must, should, must_not
  • Loading branch information
esmarkowski authored Mar 28, 2024
2 parents 0e3ad3b + afce5af commit d1c34b6
Show file tree
Hide file tree
Showing 4 changed files with 126 additions and 4 deletions.
58 changes: 58 additions & 0 deletions docs/guides/querying.md
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,64 @@ You can pass one or more key-value pairs to `.where` to search for documents whe
Model.where(color: 'blue', :title: "Candy")
```

>[!INFO|label:Default Behavior|style:flat]
> The default behavior is to create a term query for each argument against keyword fields.
```ruby
Model.must(file_name: 'rb', content: '.where')
```

```ruby
{
"query" => {
"bool" => {
"must" => [
{
"term" => {
"file_name.keyword" => "rb"
}
},
{
"term" => {
"content.keyword" => ".where"
}
}
]
}
}
}
```

For `match` behavior the query can be modified like so:

```ruby
Model.must(match: {file_name: '*.rb', content: '.where'})
#or Model.where(match: {file_name: '*.rb', content: '.where'})
```

```ruby
{
"query" => {
"bool" => {
"must" => [
{
"match" => {
"file_name" => "*.rb"
}
},
{
"match" => {
"content" => ".where"
}
}
]
}
}
}
```



##### Ranges
You can use ranges to search for documents where a field's value falls within a certain range. For example,
```ruby
Expand Down
12 changes: 9 additions & 3 deletions lib/stretchy/relations/query_builder.rb
Original file line number Diff line number Diff line change
Expand Up @@ -318,10 +318,16 @@ def as_must(q)
q.each do |arg|
case arg
when Hash
arg = keyword_transformer.transform(arg)
arg = keyword_transformer.transform(arg, :match)
arg.each_pair do |k,v|
# If v is an array, we build a terms query otherwise a term query
_must << (v.is_a?(Array) ? {terms: Hash[k,v]} : {term: Hash[k,v]})
if k == :match
v.each do |field, value|
_must << (field.is_a?(Hash) ? { k => field} : { k => {field => value}})
end
else
# If v is an array, we build a terms query otherwise a term query
_must << (v.is_a?(Array) ? {terms: Hash[k,v]} : {term: Hash[k,v]})
end
end
when String
_must << {term: Hash[[arg.split(/:/).collect(&:strip)]]}
Expand Down
4 changes: 3 additions & 1 deletion lib/stretchy/relations/query_methods/where.rb
Original file line number Diff line number Diff line change
Expand Up @@ -69,7 +69,9 @@ def where(opts = :chain, *rest)
range_options[upper_bound] = range.end
filter_query(:range, key => range_options)
when Hash
opts.delete(key)
hash = opts.delete(key)
spawn.where!(key => hash) if [:match, :match_phrase, :match_phrase_prefix].include?(key)

filter_query(:range, key => value) if value.keys.any? { |k| [:gte, :lte, :gt, :lt].include?(k) }
when ::Regexp
opts.delete(key)
Expand Down
56 changes: 56 additions & 0 deletions spec/stretchy/relations/query_methods/where_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,13 @@
end
end

context 'match' do
it 'handles match' do
relation.where(match: {title: 'Fun times'})
expect(relation_values).to eq([match: {title: 'Fun times'}])
end
end


context 'when using ranges' do
let(:relation_filter_values) { relation.values[:filter_query] }
Expand Down Expand Up @@ -218,5 +225,54 @@
end
end

context 'match' do
it 'is a match query' do
values[:where] = [{match: {name: 'Fun times'}}]
expect(clause).to eq(
{
match: {
name: 'Fun times'
}
}
)
end

it 'multiple fields per match' do
values[:where] = [{:match=>{:file_name=>"*.rb", :content=>".where"}}]
expect(clause).to eq(
[
{
match: {
file_name: "*.rb",
},
},
{
match: {
content: ".where"
}
}
]
)
end

it 'is a match query for each distinct field' do
values[:where] = [{match: {name: 'Fun times'}}, {match: {color: 'blue'}}]
expect(clause).to eq(
[
{
match: {
name: 'Fun times'
}
},
{
match: {
color: 'blue'
}
}
]
)
end
end

end
end

0 comments on commit d1c34b6

Please sign in to comment.