]> git.openstreetmap.org Git - rails.git/blob - app/controllers/search_controller.rb
Use QuadTiling in GPS point queries.
[rails.git] / app / controllers / search_controller.rb
1 class SearchController < ApplicationController
2   # Support searching for nodes, segments, ways, or all
3   # Can search by tag k, v, or both (type->k,value->v)
4   # Can search by name (k=name,v=....)
5
6   after_filter :compress_output
7
8   def search_all
9     do_search(true,true,true)
10   end
11
12   def search_ways
13     do_search(true,false,false)
14   end
15   def search_segments
16     do_search(false,true,false)
17   end
18   def search_nodes
19     do_search(false,false,true)
20   end
21
22
23   def do_search(do_ways,do_segments,do_nodes)
24     type = params['type']
25     value = params['value']
26     unless type or value
27       name = params['name']
28       if name
29         type = 'name'
30         value = name
31       end
32     end
33
34     way_ids = Array.new
35     ways = Array.new
36     segments = Array.new
37     nodes = Array.new
38
39     # Matching for tags table
40     cond_tbl = Array.new
41     sql = 'id IN (SELECT id FROM current_way_tags WHERE 1=1'
42     if type
43       sql += ' AND k=?'
44       cond_tbl += [type]
45     end
46     if value
47       sql += ' AND v=?'
48       cond_tbl += [value]
49     end
50     sql += ')'
51     cond_tbl = [sql] + cond_tbl
52
53     # Matching for tags column
54     if type and value
55       cond_tags = ['tags LIKE ? OR tags LIKE ? OR tags LIKE ? OR tags LIKE ?', 
56       ''+type+'='+value+'',
57       ''+type+'='+value+';%',
58       '%;'+type+'='+value+';%',
59       '%;'+type+'='+value+'' ]
60     elsif type
61       cond_tags = ['tags LIKE ? OR tags LIKE ?',
62       ''+type+'=%',
63       '%;'+type+'=%' ]
64     elsif value
65       cond_tags = ['tags LIKE ? OR tags LIKE ?',
66       '%='+value+';%',
67       '%='+value+'' ]
68     else
69       cond_tags = ['1=1']
70     end
71
72
73     # First up, look for the ways we want
74     if do_ways
75       ways = Way.find(:all, :conditions => cond_tbl, :limit => 100)
76     end
77
78     # Now, segments matching
79     if do_segments
80       segments = Segment.find(:all, :conditions => cond_tags, :limit => 500)
81     end
82
83     # Now, nodes
84     if do_nodes
85       nodes = Node.find(:all, :conditions => cond_tags, :limit => 2000)
86     end
87
88     # Fetch any segments needed for our ways (only have matching segments so far)
89     segments += Segment.find(ways.collect { |w| w.segs }.uniq)
90
91     # Fetch any nodes needed for our segments (only have matching nodes so far)
92     nodes += Node.find(segments.collect { |s| [s.node_a, s.node_b] }.flatten.uniq)
93
94     # Print
95     user_display_name_cache = {}
96     doc = OSM::API.new.get_xml_doc
97     nodes.each do |node|
98       doc.root << node.to_xml_node(user_display_name_cache)
99     end
100
101     segments.each do |segment|
102       doc.root << segment.to_xml_node(user_display_name_cache)
103     end 
104
105     ways.each do |way|
106       doc.root << way.to_xml_node(user_display_name_cache)
107     end 
108
109     render :text => doc.to_s, :content_type => "text/xml"
110   end
111 end