summaryrefslogtreecommitdiff
path: root/web/lib
diff options
context:
space:
mode:
authorJochen Topf <jochen@topf.org>2010-11-22 17:34:58 +0100
committerJochen Topf <jochen@topf.org>2010-11-22 17:34:58 +0100
commitd7b01517714d16c3d8f57c34607a2579bd7ae8eb (patch)
tree503d3b8bd7451619629b069b2446ef58ae2dab0b /web/lib
parent38d2c23e137c4cd7fb454db78b0a1981af5e3571 (diff)
downloadtaginfo-d7b01517714d16c3d8f57c34607a2579bd7ae8eb.tar
taginfo-d7b01517714d16c3d8f57c34607a2579bd7ae8eb.tar.gz
Improved search and some more translations
Diffstat (limited to 'web/lib')
-rw-r--r--web/lib/api/search.rb62
-rw-r--r--web/lib/sql.rb2
-rw-r--r--web/lib/ui/search.rb81
-rw-r--r--web/lib/utils.rb5
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
+