Начало разработки логики обработки слов.

This commit is contained in:
Jack Stdin
2016-01-16 15:53:13 +03:00
parent 327a1c994e
commit 6c09dd2cdb
9 changed files with 104 additions and 49 deletions

View File

@@ -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
View 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)