diff options
author | Jochen Topf <jochen@topf.org> | 2010-11-22 17:34:58 +0100 |
---|---|---|
committer | Jochen Topf <jochen@topf.org> | 2010-11-22 17:34:58 +0100 |
commit | d7b01517714d16c3d8f57c34607a2579bd7ae8eb (patch) | |
tree | 503d3b8bd7451619629b069b2446ef58ae2dab0b /web/lib | |
parent | 38d2c23e137c4cd7fb454db78b0a1981af5e3571 (diff) | |
download | taginfo-d7b01517714d16c3d8f57c34607a2579bd7ae8eb.tar taginfo-d7b01517714d16c3d8f57c34607a2579bd7ae8eb.tar.gz |
Improved search and some more translations
Diffstat (limited to 'web/lib')
-rw-r--r-- | web/lib/api/search.rb | 62 | ||||
-rw-r--r-- | web/lib/sql.rb | 2 | ||||
-rw-r--r-- | web/lib/ui/search.rb | 81 | ||||
-rw-r--r-- | web/lib/utils.rb | 5 |
4 files changed, 138 insertions, 12 deletions
diff --git a/web/lib/api/search.rb b/web/lib/api/search.rb new file mode 100644 index 0000000..63b266f --- /dev/null +++ b/web/lib/api/search.rb @@ -0,0 +1,62 @@ +# web/lib/api/search.rb +class Taginfo < Sinatra::Base + + get '/api/2/search/keys' do + query = params[:q] + end + + get '/api/2/search/values' do + query = params[:q] + + total = @db.count('search.ftsearch'). + condition_if("value MATCH ?", query). + get_first_value().to_i + + res = @db.select('SELECT * FROM search.ftsearch'). + condition_if("value MATCH ?", query). + order_by([:count_all], 'DESC'). + paging(params[:rp], params[:page]). + execute() + + return { + :page => params[:page].to_i, + :rp => params[:rp].to_i, + :total => total, + :data => res.map{ |row| { + :key => row['key'], + :value => row['value'], + :count_all => row['count_all'].to_i, + }} + }.to_json + end + + get '/api/2/search/tags' do + query = params[:q] + query =~ /(.*)=(.*)/ + query_key = $1 + query_value = $2 + + total = @db.execute('SELECT count(*) FROM (SELECT * FROM search.ftsearch WHERE key MATCH ? INTERSECT SELECT * FROM search.ftsearch WHERE value MATCH ?)', query_key, query_value)[0][0].to_i + + res = @db.select('SELECT * FROM search.ftsearch WHERE key MATCH ? INTERSECT SELECT * FROM search.ftsearch WHERE value MATCH ?', query_key, query_value). + order_by([:count_all], 'DESC'). + paging(params[:rp], params[:page]). + execute() + + return { + :page => params[:page].to_i, + :rp => params[:rp].to_i, + :total => total, + :data => res.map{ |row| { + :key => row['key'], + :value => row['value'], + :count_all => row['count_all'].to_i, + }} + }.to_json + end + + get '/api/2/search/wiki' do + query = params[:q] + end + +end diff --git a/web/lib/sql.rb b/web/lib/sql.rb index 9b85118..4269421 100644 --- a/web/lib/sql.rb +++ b/web/lib/sql.rb @@ -11,7 +11,7 @@ module SQL @db = SQLite3::Database.new(filename) @db.results_as_hash = true - [:db, :wiki, :josm, :potlatch, :merkaartor].each do |dbname| + [:db, :wiki, :josm, :potlatch, :merkaartor, :search].each do |dbname| @db.execute("ATTACH DATABASE '#{dir}/taginfo-#{dbname}.db' AS #{dbname}") end diff --git a/web/lib/ui/search.rb b/web/lib/ui/search.rb index 0a93e2c..8592d3f 100644 --- a/web/lib/ui/search.rb +++ b/web/lib/ui/search.rb @@ -1,23 +1,82 @@ # web/lib/ui/search.rb class Taginfo < Sinatra::Base + # The search results page get '/search' do - @title = 'Search results' + @title = t.pages.search.results.title @breadcrumbs << @title - @escaped_search_string = escape_html(params[:search]) + @query = params[:q] + if @query =~ /(.*)=(.*)/ + erb :search_tags + else + erb :search + end + end + + # Return opensearch description (see www.opensearch.org) + get '/search/opensearch.xml' do + content_type :opensearch + opensearch = <<END_XML +<?xml version="1.0" encoding="UTF-8"?> +<OpenSearchDescription xmlns="http://a9.com/-/spec/opensearch/1.1/"> + <ShortName>Taginfo</ShortName> + <Description>Find metadata about OpenStreetMap tags</Description> + <Tags>osm openstreetmap tag tags taginfo</Tags> + <Contact>admin@openstreetmap.de</Contact> + <Url type="application/x-suggestions+json" rel="suggestions" template="__URL__/search/suggest?term={searchTerms}"/> + <Url type="text/html" method="get" template="__URL__/search?q={searchTerms}"/> + <Url type="application/opensearchdescription+xml" rel="self" template="__URL__/opensearch.xml"/> + <Image height="16" width="16" type="image/x-icon">__URL__/favicon.ico</Image> +</OpenSearchDescription> +END_XML + return opensearch.gsub(/__URL__/, base_url) + end + + # Returns search suggestions as per OpenSearch standard + get '/search/suggest' do + query = params[:term] + format = params[:format] - @key = @db.select('SELECT key FROM keys'). - condition('key = ?', params[:search]). - get_first_value() + sel = @db.select('SELECT * FROM suggestions'). + order_by([:score], 'DESC'). + limit(10) - @substring_keys = @db.select('SELECT key FROM keys'). - condition("key LIKE '%' || ? || '%' AND key != ?", params[:search], params[:search]). - order_by(:key). - execute(). - map{ |row| row['key'] } + if query =~ /^=(.*)/ + value = $1 + res = sel. + condition_if("value LIKE ? || '%'", value). + execute(). + map{ |row| row['key'] + '=' + row['value'] } + elsif query =~ /(.*)=(.*)/ + key = $1 + value = $2 + res = sel. + condition_if("key LIKE ? || '%'", key). + condition_if("value LIKE ? || '%'", value). + execute(). + map{ |row| row['key'] + '=' + row['value'] } + else + res = sel. + condition_if("key LIKE ? || '%'", query). + condition("value IS NULL"). + execute(). + map{ |row| row['key'] } + end - erb :search + if format == 'simple' + # simple format is used by the search box on the website itself, + # it is just a list of suggestions + return res.to_json + "\n"; + else + # this is the OpenSearch standard format + return [ + query, # the query string + res, # the list of suggestions + res.map{ |item| '' }, # the standard says this is for descriptions, we don't have any so this is empty + res.map{ |item| base_url + '/tags/' + item } # the page this search should got to (ignored by FF, Chrome) + ].to_json + "\n" + end end end diff --git a/web/lib/utils.rb b/web/lib/utils.rb index c281419..d9d1f51 100644 --- a/web/lib/utils.rb +++ b/web/lib/utils.rb @@ -175,3 +175,8 @@ def get!(path, &block) end end +# return the base url for this site +def base_url + request.scheme + '://' + request.host + ':' + request.port.to_s +end + |