fulltext search in macosx
This commit is contained in:
parent
6c7d6bb6b0
commit
1c8a5c3764
5 changed files with 59 additions and 2 deletions
|
@ -241,6 +241,12 @@
|
||||||
"format": {"type": "boolean", "args": []},
|
"format": {"type": "boolean", "args": []},
|
||||||
"sort": true
|
"sort": true
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
"id": "fulltext",
|
||||||
|
"title": "Full Text",
|
||||||
|
"find": true,
|
||||||
|
"type": "text"
|
||||||
|
},
|
||||||
{
|
{
|
||||||
"id": "random",
|
"id": "random",
|
||||||
"title": "Random",
|
"title": "Random",
|
||||||
|
|
28
oml/fulltext.py
Normal file
28
oml/fulltext.py
Normal file
|
@ -0,0 +1,28 @@
|
||||||
|
import logging
|
||||||
|
import os
|
||||||
|
import subprocess
|
||||||
|
import sys
|
||||||
|
|
||||||
|
|
||||||
|
logger = logging.getLogger(__name__)
|
||||||
|
|
||||||
|
def find_fulltext_macos(query):
|
||||||
|
import settings
|
||||||
|
from item.models import File
|
||||||
|
prefix = os.path.join(os.path.expanduser(settings.preferences['libraryPath']), 'Books/')
|
||||||
|
cmd = ["mdfind", "-onlyin", prefix, query]
|
||||||
|
books = subprocess.check_output(cmd).decode().strip().split('\n')
|
||||||
|
books = [path[len(prefix):] for path in books]
|
||||||
|
ids = [b[0] for b in File.query.filter(operators.in_op(File.path, books)).values('sha1')]
|
||||||
|
return ids
|
||||||
|
|
||||||
|
def find_fulltext(query):
|
||||||
|
ids = []
|
||||||
|
if sys.platform == 'darwin':
|
||||||
|
ids = find_fulltext_macos(query)
|
||||||
|
else:
|
||||||
|
logger.debug('missing fulltext search implementation for %s', sys.platform)
|
||||||
|
return ids
|
||||||
|
|
||||||
|
def platform_supported():
|
||||||
|
return sys.platform == 'darwin'
|
|
@ -9,6 +9,7 @@ from sqlalchemy.sql.expression import text
|
||||||
|
|
||||||
import utils
|
import utils
|
||||||
import settings
|
import settings
|
||||||
|
from fulltext import find_fulltext
|
||||||
|
|
||||||
import logging
|
import logging
|
||||||
logger = logging.getLogger(__name__)
|
logger = logging.getLogger(__name__)
|
||||||
|
@ -25,7 +26,7 @@ def get_operator(op, type='str'):
|
||||||
'$': operators.endswith_op,
|
'$': operators.endswith_op,
|
||||||
'&': operators.in_op,
|
'&': operators.in_op,
|
||||||
},
|
},
|
||||||
'int': {
|
'int': {
|
||||||
'==': operators.eq,
|
'==': operators.eq,
|
||||||
'>': operators.gt,
|
'>': operators.gt,
|
||||||
'>=': operators.ge,
|
'>=': operators.ge,
|
||||||
|
@ -65,7 +66,7 @@ class Parser(object):
|
||||||
...
|
...
|
||||||
'''
|
'''
|
||||||
#logger.debug('parse_condition %s', condition)
|
#logger.debug('parse_condition %s', condition)
|
||||||
if not 'value' in condition:
|
if 'value' not in condition:
|
||||||
return None
|
return None
|
||||||
k = condition.get('key', '*')
|
k = condition.get('key', '*')
|
||||||
if not k:
|
if not k:
|
||||||
|
@ -122,6 +123,18 @@ class Parser(object):
|
||||||
in_op = operators.notin_op if exclude else operators.in_op
|
in_op = operators.notin_op if exclude else operators.in_op
|
||||||
q = in_op(self._model.id, ids)
|
q = in_op(self._model.id, ids)
|
||||||
return q
|
return q
|
||||||
|
elif k == 'fulltext':
|
||||||
|
ids = find_fulltext(v)
|
||||||
|
if ids:
|
||||||
|
in_op = operators.notin_op if exclude else operators.in_op
|
||||||
|
q = in_op(self._model.id, ids)
|
||||||
|
else:
|
||||||
|
# nothing
|
||||||
|
q = operators.eq(self._model.id, -1)
|
||||||
|
if exclude:
|
||||||
|
q = ~q
|
||||||
|
return q
|
||||||
|
|
||||||
elif key_type in ("string", "text"):
|
elif key_type in ("string", "text"):
|
||||||
if isinstance(v, str):
|
if isinstance(v, str):
|
||||||
v = unicodedata.normalize('NFKD', v).lower()
|
v = unicodedata.normalize('NFKD', v).lower()
|
||||||
|
|
|
@ -6,6 +6,7 @@ import os
|
||||||
|
|
||||||
from oml.pdict import pdict
|
from oml.pdict import pdict
|
||||||
from oml.utils import get_user_id
|
from oml.utils import get_user_id
|
||||||
|
from oml import fulltext
|
||||||
|
|
||||||
base_dir = os.path.normpath(os.path.join(os.path.abspath(os.path.dirname(__file__)), '..'))
|
base_dir = os.path.normpath(os.path.join(os.path.abspath(os.path.dirname(__file__)), '..'))
|
||||||
static_path = os.path.join(base_dir, 'static')
|
static_path = os.path.join(base_dir, 'static')
|
||||||
|
@ -90,3 +91,10 @@ DEBUG_HTTP = server.get('debug_http', False)
|
||||||
DEBUG_API = server.get('debug_api', False)
|
DEBUG_API = server.get('debug_api', False)
|
||||||
|
|
||||||
DB_VERSION = 13
|
DB_VERSION = 13
|
||||||
|
|
||||||
|
|
||||||
|
FULLTEXT_SUPPORT = fulltext.platform_supported()
|
||||||
|
|
||||||
|
if not FULLTEXT_SUPPORT:
|
||||||
|
config['itemKeys'] = [k for k in config['itemKeys'] if k['id'] != 'fulltext']
|
||||||
|
|
||||||
|
|
|
@ -35,6 +35,8 @@ def init(data):
|
||||||
if os.path.exists(settings.oml_data_path):
|
if os.path.exists(settings.oml_data_path):
|
||||||
with open(settings.oml_data_path) as fd:
|
with open(settings.oml_data_path) as fd:
|
||||||
config = json.load(fd)
|
config = json.load(fd)
|
||||||
|
if not settings.FULLTEXT_SUPPORT:
|
||||||
|
config['itemKeys'] = [k for k in config['itemKeys'] if k['id'] != 'fulltext']
|
||||||
else:
|
else:
|
||||||
config = {}
|
config = {}
|
||||||
response['config'] = config
|
response['config'] = config
|
||||||
|
|
Loading…
Add table
Reference in a new issue