diff --git a/libraries/search/overrides.rb b/libraries/search/overrides.rb index b7af1f6..ccbc5d6 100644 --- a/libraries/search/overrides.rb +++ b/libraries/search/overrides.rb @@ -33,7 +33,7 @@ module Overrides # This search() method returns a block iterator or an Array, depending # on how this method is called. def search(obj, query=nil, sort=nil, start=0, rows=1000, &block) - if !sort.nil? + if !sort.nil? and sort.keys != [:filter_result] raise "Sorting search results is not supported" end _query = Query.parse(query) @@ -54,6 +54,9 @@ def search(obj, query=nil, sort=nil, start=0, rows=1000, &block) _result += bags end + if sort.respond_to?(:has_key?) and sort.has_key?(:filter_result) + _result.map! { |r| apply_filter_result(r, sort[:filter_result]) } + end if block_given? pos = 0 @@ -66,6 +69,23 @@ def search(obj, query=nil, sort=nil, start=0, rows=1000, &block) end end + def apply_filter_result(result, filter) + filtered = {} + filter.each_pair do |k, path| + filtered[k.to_s] = hash_path(result, path) + end + filtered + end + + def hash_path(value, path) + path.each do |k| + value = value[k] + end + value + rescue + nil + end + def search_nodes(_query, start, rows, &block) _result = [] node_path = Chef::Config[:nodes_path] || File.join(Chef::Config[:data_bag_path], "node") diff --git a/tests/test_search.rb b/tests/test_search.rb index 797b0e3..f8eda83 100644 --- a/tests/test_search.rb +++ b/tests/test_search.rb @@ -30,7 +30,7 @@ require File.expand_path('../../libraries/search', __FILE__) module SearchDbTests - + def test_search_all # try to get data of all users nodes = search(:users, "*:*") @@ -40,19 +40,19 @@ def test_search_all nodes = search(:users, nil) assert_equal nodes.length, 4 end - + def test_search_exact_match nodes = search(:users, "username:speedy") assert_equal nodes.length, 1 assert_equal nodes[0]["username"], "speedy" end - + def test_get_all_with_field nodes = search(:users, "username:*") assert nodes.length > 0 assert nodes.all?{|x| !x["username"].nil?} end - + def test_get_all_without_field nodes = search(:users, "(NOT username:*)") assert nodes.length == 0 @@ -60,13 +60,13 @@ def test_get_all_without_field assert nodes.length == 3 assert nodes.all?{|x| x["color"].nil?} end - + def test_get_all_but_speedy nodes = search(:users, "NOT username:speedy") assert nodes.length > 0 assert nodes.all?{|x| x["username"] != "speedy"} end - + def test_array_includes nodes = search(:users, "children:tom") assert nodes.length == 2 @@ -75,7 +75,7 @@ def test_array_includes assert nodes.length == 1 assert nodes.all?{ |x| x["children"].include?("jerry") } end - + def test_boolean nodes = search(:users, "married:true") assert nodes.length == 3 @@ -84,24 +84,24 @@ def test_boolean assert nodes.length == 1 assert nodes[0]["married"] == false end - + def test_integer nodes = search(:users, "age:35") assert nodes.length == 1 assert nodes[0]["age"] == 35 end - + def test_AND_condition nodes = search(:users, "married:true AND age:35") assert nodes.length == 1 assert nodes[0]["username"] == "lea" end - + def test_OR_condition nodes = search(:users, "age:42 OR age:22") assert nodes.length == 2 end - + def test_NOT_condition nodes = search(:users, "children:tom AND (NOT gender:female)") assert nodes.length == 1 @@ -110,29 +110,29 @@ def test_NOT_condition nodes = search(:users, "children:tom AND (NOT gender:female) AND (NOT age:42)") assert nodes.length == 0 end - + def test_any_value nodes = search(:users, "children:*") assert nodes.length == 2 end - + def test_any_value_lucene_range nodes = search(:users, "address:[* TO *]") assert nodes.length == 2 end - + def test_general_lucene_range_fails assert_raises RuntimeError do nodes = search(:users, "children:[aaa TO zzz]") end end - + def test_block_usage # bracket syntax result = [] search(:users, "*:*") {|x| result << x["id"]} assert result.length == 4 - + # do...end syntax result = [] search(:users) do |x| @@ -140,7 +140,7 @@ def test_block_usage end assert result.length == 4 end - + def test_check_escaped_chars nodes = search(:users, 'tag:tag\:\:test') assert nodes.length == 1 @@ -155,7 +155,7 @@ def test_check_escaped_chars nodes = search(:users, "tags:tag\\:\\:*") assert nodes.length == 1 end - + def test_wildcards nodes = search(:users, "gender:f??ale") assert nodes.length == 1 @@ -164,7 +164,7 @@ def test_wildcards nodes = search(:users, "username:spee*") assert nodes.length == 1 end - + def test_empty_field_value assert_raise(RuntimeError) { search(:users, "gender:#{nil} AND age:35") @@ -176,18 +176,26 @@ def test_empty_field_value search(:users, "gender:\"\" AND age:35") } end - + def test_OR_group nodes = search(:users, "id:(mike OR tom)") assert nodes.length == 2 end - + def test_nested_fieldnames nodes = search(:users, "address_street:wilhelmsstrasse") assert nodes.length == 1 nodes = search(:users, "address_street_floor:1") assert nodes.length == 1 end + + def test_search_with_filter_result + nodes = search(:users, "id:(mike OR tom)", :filter_result => { + :addr => ['address', 'street', 'floor'] + }) + assert_equal 1, nodes[0]['addr'] + assert_equal nil, nodes[1]['addr'] + end end module SearchNodeTests @@ -218,6 +226,13 @@ def test_search_node_without_json_class nodes = search(:node, "chef_environment:default") assert_equal 3, nodes.length end + + def test_search_with_filter_result + nodes = search(:node, "chef_environment:default", :filter_result => { + :hostname => ['hostname'] + }) + assert_equal [['hostname'], ['hostname'], ['hostname']], nodes.map(&:keys) + end end module ImplicitSearchDB