view lucene/src/luan/modules/lucene/Lucene.luan @ 540:4362eb720da9

add Number module
author Franklin Schmidt <fschmidt@gmail.com>
date Mon, 01 Jun 2015 18:04:50 -0600
parents 919b9410008e
children 7170a0c414d5
line wrap: on
line source

java()
local Luan = require "luan:Luan"
local pairs = Luan.pairs
local ipairs = Luan.ipairs
local type = Luan.type
local number_type = Luan.number_type
local error = Luan.error
local Number = require "luan:Number"
local number_type = Number.number_type
local Table = require "luan:Table"
local unpack = Table.unpack
local LuceneIndex = require "java:luan.modules.lucene.LuceneIndex"
local Term = require "java:org.apache.lucene.index.Term"
local TermQuery = require "java:org.apache.lucene.search.TermQuery"
local TermRangeQuery = require "java:org.apache.lucene.search.TermRangeQuery"
local NumericRangeQuery = require "java:org.apache.lucene.search.NumericRangeQuery"
local MatchAllDocsQuery = require "java:org.apache.lucene.search.MatchAllDocsQuery"
local BooleanQuery = require "java:org.apache.lucene.search.BooleanQuery"
local BooleanClause = require "java:org.apache.lucene.search.BooleanClause"
local Sort = require "java:org.apache.lucene.search.Sort"
local SortField = require "java:org.apache.lucene.search.SortField"

local M = {}

function M.index(indexDir)
	local index = {}
	local java_index = LuceneIndex.new(indexDir)
	index.fields = java_index.fields.newTable()
	index.to_string = java_index.to_string
	index.backup = java_index.backup
	index.Writer = java_index.Writer
	index.Searcher = java_index.Searcher
	index.delete_all = java_index.delete_all
	index.map_field_name = java_index.map_field_name
	index.close = java_index.close

	function index.save_document(doc)
		index.Writer( function(writer)
			writer.save_document(doc)
		end )
	end

	function index.delete_documents(terms)
		index.Writer( function(writer)
			writer.delete_documents(terms)
		end )
	end

	function index.get_first(query, sort)
		return index.Searcher( function(searcher)
			local results, _, total_hits = searcher.search(query,1,sort)
			return results(), total_hits
		end )
	end

	function index.get_document(query)
		local doc, total_hits = index.get_first(query);
		if total_hits > 1 then
			error( "found " .. total_hits .. " documents" )
		end
		return doc
	end

	function index.count(query)
		return index.Searcher( function(searcher)
			local _, _, total_hits = searcher.search(query,0)
			return total_hits
		end )
	end



	local queryTbl = {}
	index.query = queryTbl

	queryTbl.parse = java_index.parse

	queryTbl.all_docs = MatchAllDocsQuery.new()
	
	function queryTbl.term(field,value)
		if value==nil and type(field)=="table" then
			local iter = pairs(field)
			field, value = iter()
			iter()==nil or error "only one term allowed"
		end
		field and value or error "missing term"
		field = index.map_field_name(field)
		local tp = type(value)
		if tp == "string" then
			return TermQuery.new(Term.new(field,value))
		end
		if tp == "number" then
			return queryTbl.range(field,value,value)
		end
		error("invalid term value type: "..tp)
	end

	function queryTbl.range(field,min,max,include_min,include_max)
		if include_min == nil then include_min = true end
		if include_max == nil then include_max = true end
		field = index.map_field_name(field)
		local tp = type(min)
		tp == type(max) or error "min and max types don't match"
		if tp == "string" then
			return TermRangeQuery.newStringRange(field,min,max,include_min,include_max)
		end
		if tp == "number" then
			tp = number_type(min)
			tp == number_type(max) or error "min and max number types don't match"
			if tp == "integer" then
				return NumericRangeQuery.newIntRange(field,min,max,include_min,include_max)
			end
			if tp == "long" then
				return NumericRangeQuery.newLongRange(field,min,max,include_min,include_max)
			end
			if tp == "double" then
				return NumericRangeQuery.newDoubleRange(field,min,max,include_min,include_max)
			end
			error("invalid term value type: "..tp)
		end
		error("invalid term value type: "..tp)
	end

	function queryTbl.boolean(t)
		local boolean_query = BooleanQuery.new()
		for query, occur_string in pairs(t) do
			local occur = BooleanClause.Occur.valueOf( occur_string.upper() )
			boolean_query.add( query, occur )
		end
		return boolean_query
	end
	
	-- and list
	function queryTbl.all(t)
		local bt = {}
		for key, query in pairs(t) do
			if type(key)=="string" then
				query = queryTbl.term{[key]=query}
			end
			bt[query] = "MUST"
		end
		return queryTbl.boolean(bt)
	end
	
	-- or list
	function queryTbl.any(t)
		local bt = {}
		for key, query in pairs(t) do
			if type(key)=="string" then
				query = queryTbl.term{[key]=query}
			end
			bt[query] = "SHOULD"
		end
		return queryTbl.boolean(bt)
	end
	
	
	function queryTbl.sort(fields)
		#fields > 0 or error "list of sort fields expected"
		local a = {}
		for _, f in ipairs(fields) do
			f.field or error "missing sort field"
			f.type or error "missing sort type"
			local field = index.map_field_name(f.field)
			local type = SortField.Type.valueOf( f.type.upper() )
			local reverse = f.reverse or false
			a[#a+1] = SortField.new(field,type,reverse)
		end
		return Sort.new(unpack(a))
	end


	return index
end

return M