Начало разработки логики обработки слов.
This commit is contained in:
parent
327a1c994e
commit
6c09dd2cdb
@ -24,6 +24,7 @@ class DBImpl:
|
||||
def execute(self, sql_query):
|
||||
try:
|
||||
cur = self.get_cursor()
|
||||
print sql_query
|
||||
cur.execute(sql_query)
|
||||
self.transaction_commit()
|
||||
except:
|
||||
|
@ -18,7 +18,7 @@ db_shemas['ADDROBJ'] = DbSchema("ADDROBJ",
|
||||
db_shemas['SOCRBASE'] = DbSchema("SOCRBASE", ["LEVEL", "SOCRNAME", "SCNAME", "KOD_T_ST"], "kod_t_st",
|
||||
"AddressObjectType")
|
||||
|
||||
db_shemas['AOTRIG'] = DbSchema("AOTRIG", ["WORD", "TRIGRAMM"], "word",
|
||||
db_shemas['AOTRIG'] = DbSchema("AOTRIG", ["WORD", "TRIGRAMM", "FREQUENCY"], "word",
|
||||
None)
|
||||
|
||||
allowed_tables = ["ADDROBJ", "SOCRBASE"]
|
||||
|
@ -8,6 +8,7 @@ import sphinxapi
|
||||
|
||||
from aore.config import db as dbparams
|
||||
from aore.dbutils.dbimpl import DBImpl
|
||||
from aore.fias.word import WordEntry
|
||||
from aore.miscutils.trigram import trigram
|
||||
|
||||
|
||||
@ -30,44 +31,6 @@ class SphinxSearch:
|
||||
else:
|
||||
self.client.SetMatchMode(sphinxapi.MA)
|
||||
|
||||
# Types =
|
||||
class SRankType:
|
||||
names = dict(
|
||||
SRANK_EXACTLY_MISSPRINT=['00'], # Точно - опечатка, нужно много подсказок, без word*
|
||||
SRANK_EXACTLY_TYPING=['01', '11'], # Точно - слово недопечатано, не надо подсказок, только word*
|
||||
SRANK_PROBABLY_TYPING=['0*'], # Возможно - слово недопечатано, немного подсказок и word*
|
||||
SRANK_PROBABLY_FOUND=['10'], # Возможно - слово введено точно, немного подсказок, без word*
|
||||
SRANK_PROBABLY_COMPLEX=['1*'],
|
||||
# Возможно, слово сложное, есть и точное совпадние, по маске Нужно немного подсказок и word*
|
||||
SRANK_PROBABLY_SOCR=['1!'] # Возможно - сокращение, не трогаем вообще
|
||||
)
|
||||
|
||||
def __init__(self, rtype):
|
||||
self.rtype = rtype
|
||||
for x, y in self.names.iteritems():
|
||||
self.__dict__[x] = self.rtype in y
|
||||
|
||||
def __str__(self):
|
||||
return ", ".join([x for x in self.names if self.__dict__[x]])
|
||||
|
||||
def __get_strong_and_uncomplete_ranks(self, word):
|
||||
word_len = len(word)
|
||||
sql_qry = "SELECT COUNT(*) FROM \"AOTRIG\" WHERE word LIKE '{}%' AND LENGTH(word) > {} " \
|
||||
"UNION ALL SELECT COUNT(*) FROM \"AOTRIG\" WHERE word='{}'".format(
|
||||
word, word_len, word)
|
||||
|
||||
result = self.db.get_rows(sql_qry)
|
||||
strong_rank = result[1][0]
|
||||
uncomplete_rank = result[0][0]
|
||||
|
||||
if uncomplete_rank > 1000 and word_len < 4:
|
||||
uncomplete_rank = '!'
|
||||
else:
|
||||
if uncomplete_rank > 1:
|
||||
uncomplete_rank = '*'
|
||||
|
||||
return self.SRankType(str(strong_rank) + str(uncomplete_rank))
|
||||
|
||||
def __get_suggest(self, word):
|
||||
word_len = str(len(word) / 2)
|
||||
trigrammed_word = '"{}"/1'.format(trigram(word))
|
||||
@ -95,13 +58,15 @@ class SphinxSearch:
|
||||
phrase = unicode(phrase).replace('-', '').replace('@', '').lower()
|
||||
return re.split(r"[ ,:.]+", phrase)
|
||||
|
||||
def __process_word(self, word):
|
||||
print word, self.__get_strong_and_uncomplete_ranks(word)
|
||||
def __process_words(self, words):
|
||||
for word in words:
|
||||
yield WordEntry(self.db, word)
|
||||
|
||||
def find(self, text):
|
||||
words = self.__split_phrase(text)
|
||||
for word in words:
|
||||
self.__process_word(word)
|
||||
word_entries = self.__process_words(words)
|
||||
for word_entry in word_entries:
|
||||
print word_entry, word_entry.get_type()
|
||||
# result = self.client.Query(text)
|
||||
# print json.dumps(result)
|
||||
# logging.info("12")
|
||||
|
73
aore/fias/word.py
Normal file
73
aore/fias/word.py
Normal file
@ -0,0 +1,73 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
import re
|
||||
|
||||
|
||||
class WordEntry:
|
||||
# Варианты распеределния для слов с первыми двумя символами, где:
|
||||
# 0 - не найдено, 1 - найдено одно, x - найдено много (>1)
|
||||
# 1st - кол-во слов по LIKE 'word%'
|
||||
# 2nd - кол-во слов по точному совпадению
|
||||
#
|
||||
# 00 - не найдено ничего вообще. Опечатка или дряное слово. Ищем с подсказками (много)
|
||||
# 01 - найдено одно точное совпадение, но нет лайков. Оставляем как есть.
|
||||
# -0x - найдено много точных совпадений и... быть не может, там уник.
|
||||
# 10 - найден один по лайку и ни одного точного. Недопечатка. * и немного подсказок.
|
||||
# 11 - одно по лайку и одно точное. Нашли. Оставляем слово как есть.
|
||||
# -1x - одно по лайку и много точных. Быть не может.
|
||||
# x0 - много по лайку и нет точных. Недопечатка. Немного подсказок и *.
|
||||
# x1 - много по лайку и один точный. Чет нашли. Как есть и *.
|
||||
# xx - много по лайку и много точных. Оставляем как есть и *
|
||||
#
|
||||
# Теперь по сокращениям. Они работюат отдельно (ПОКА ЧТО)
|
||||
# 3rd - кол-во слов по точному совпдению по полному сокращению.
|
||||
# 4th - кол-во слов по точному совпадению по малому сокращению.
|
||||
#
|
||||
# 00 - ни найдено нигде. Значит, не сокращение (или с опечаткой). Не обрабатываем.
|
||||
# 01 - найдено одно малое сокращение. Оставляем как есть (малые и так в словаре)
|
||||
# 0x - найдено много малых. Не обрабатываем.
|
||||
# 10 - найдено одно полное и 0 малых. Добавляем малое.
|
||||
# 11 - найдено одно полное и одно малое. Бывает (допустим, 'сад'). Добавляем как есть.
|
||||
# -1x - найдено одно полное и куча малых. Ну бред.
|
||||
# x0 - найдено куча полных и ни одного малого. Добавляем малое.
|
||||
# x1 - Куча полных и 1 малое. TODO Хз, бывает ли. Не обрабатываем.
|
||||
# xx - Куча полных и куча малых. Не обрабатываем.
|
||||
match_types = dict(
|
||||
MT_MANY_SUGG=['0000'],
|
||||
MT_SOME_SUGG=['10..', 'x0..'],
|
||||
MT_LAST_STAR=['10..', 'x...'],
|
||||
MT_AS_IS=['.1..', '...1', '...x'],
|
||||
MT_ADD_SOCR=['..10', '..x0']
|
||||
)
|
||||
|
||||
def __init__(self, db, word):
|
||||
self.db = db
|
||||
self.word = word
|
||||
self.ranks = self.__get_word_entity()
|
||||
|
||||
for x, y in self.match_types.iteritems():
|
||||
self.__dict__[x] = False
|
||||
for z in y:
|
||||
self.__dict__[x] = self.__dict__[x] or re.search(z, self.ranks) is not None
|
||||
|
||||
def __get_word_entity(self):
|
||||
word_len = len(self.word)
|
||||
sql_qry = "SELECT COUNT(*) FROM \"AOTRIG\" WHERE word LIKE '{}%' AND LENGTH(word) > {} " \
|
||||
"UNION ALL SELECT COUNT(*) FROM \"AOTRIG\" WHERE word='{}' " \
|
||||
"UNION ALL SELECT COUNT(*) FROM \"SOCRBASE\" WHERE socrname ILIKE '{}'" \
|
||||
"UNION ALL SELECT COUNT(*) FROM \"SOCRBASE\" WHERE scname ILIKE '{}'".format(
|
||||
self.word, word_len, self.word, self.word, self.word)
|
||||
|
||||
result = self.db.get_rows(sql_qry)
|
||||
outmask = ""
|
||||
for ra in result:
|
||||
if ra[0] > 1:
|
||||
outmask += 'x'
|
||||
else:
|
||||
outmask += str(ra[0])
|
||||
return outmask
|
||||
|
||||
def get_type(self):
|
||||
return ", ".join([x for x in self.match_types if self.__dict__[x]])
|
||||
|
||||
def __str__(self):
|
||||
return str(self.word)
|
@ -36,7 +36,7 @@ class SphinxHelper:
|
||||
out_fname = self.__create_main_config(config_filename)
|
||||
|
||||
# Indexing both configs
|
||||
run_index_cmd = "{} -c {} --all".format(self.index_binary, out_fname)
|
||||
run_index_cmd = "{} -c {} --all --rotate".format(self.index_binary, out_fname)
|
||||
logging.info("Indexing main ({})...".format(out_fname))
|
||||
os.system(run_index_cmd)
|
||||
logging.info("All indexes were created.".format(out_fname))
|
||||
@ -81,12 +81,15 @@ class SphinxHelper:
|
||||
if line == '':
|
||||
break
|
||||
|
||||
keyword = line.split(' ')[0]
|
||||
if not keyword:
|
||||
splitting_seq = line.split(' ')
|
||||
keyword = splitting_seq[0]
|
||||
freq = splitting_seq[1].rstrip('\n')
|
||||
if not keyword or not freq:
|
||||
raise BaseException("Cannot process {}".format(self.files['dict.txt']))
|
||||
|
||||
nodes.append(keyword)
|
||||
nodes.append(trigram(keyword))
|
||||
nodes.append(freq)
|
||||
|
||||
exit_file.write("\t".join(nodes) + "\n")
|
||||
|
||||
|
@ -1,4 +1,5 @@
|
||||
CREATE INDEX "sphinx_ind_aolevel" ON "ADDROBJ" USING btree ("aolevel");
|
||||
CREATE INDEX "sphinx_ind_parentguid" ON "ADDROBJ" USING btree ("parentguid");
|
||||
CREATE INDEX "sphinx_ind_livestatus" ON "ADDROBJ" USING btree ("livestatus");
|
||||
CREATE INDEX "sphinx_ind_aoguid" ON "ADDROBJ" USING btree ("aoguid");
|
||||
CREATE INDEX "sphinx_ind_aoguid" ON "ADDROBJ" USING btree ("aoguid");
|
||||
CREATE INDEX "AOTRIG_word_idx" ON "AOTRIG" USING btree ("word");
|
@ -26,4 +26,15 @@ CREATE TABLE "SOCRBASE" (
|
||||
CONSTRAINT "id_socrbase" PRIMARY KEY ("id")
|
||||
)
|
||||
WITH (OIDS =FALSE
|
||||
);
|
||||
DROP TABLE IF EXISTS "AOTRIG";
|
||||
CREATE TABLE "AOTRIG" (
|
||||
"id" SERIAL4 NOT NULL,
|
||||
"word" VARCHAR(50),
|
||||
"trigramm" VARCHAR(180),
|
||||
"frequency" INT4,
|
||||
CONSTRAINT "word" UNIQUE ("word"),
|
||||
CONSTRAINT "id_aotrig" PRIMARY KEY ("id")
|
||||
)
|
||||
WITH (OIDS =FALSE
|
||||
);
|
@ -7,11 +7,12 @@ source {{index_name}}
|
||||
sql_db = {{db_name}}
|
||||
sql_port = {{db_port}}
|
||||
|
||||
sql_query = SELECT id, trigramm, word, LENGTH(word) AS len FROM "AOTRIG"
|
||||
sql_query = SELECT id, trigramm, word, LENGTH(word) AS len, frequency FROM "AOTRIG"
|
||||
|
||||
sql_field_string = trigramm
|
||||
sql_attr_uint = len
|
||||
sql_attr_string = word
|
||||
sql_attr_string = frequency
|
||||
}
|
||||
|
||||
index {{index_name}}
|
||||
|
Loading…
x
Reference in New Issue
Block a user