T53161 Proof of Concept working USER search. WIP js.
This commit is contained in:
parent
235a88d613
commit
8b25024f6f
@ -28,7 +28,22 @@ autocomplete = es.analyzer(
|
|||||||
class User(es.DocType):
|
class User(es.DocType):
|
||||||
"""Elastic document describing user."""
|
"""Elastic document describing user."""
|
||||||
|
|
||||||
name = es.String(
|
objectID = es.Keyword()
|
||||||
|
|
||||||
|
username = es.String(
|
||||||
|
fielddata=True,
|
||||||
|
analyzer=autocomplete,
|
||||||
|
)
|
||||||
|
|
||||||
|
full_name = es.String(
|
||||||
|
fielddata=True,
|
||||||
|
analyzer=autocomplete,
|
||||||
|
)
|
||||||
|
|
||||||
|
roles = es.Keyword(multi=True)
|
||||||
|
groups = es.Keyword(multi=True)
|
||||||
|
|
||||||
|
email = es.String(
|
||||||
fielddata=True,
|
fielddata=True,
|
||||||
analyzer=autocomplete,
|
analyzer=autocomplete,
|
||||||
)
|
)
|
||||||
@ -86,8 +101,14 @@ class Node(es.DocType):
|
|||||||
|
|
||||||
|
|
||||||
def create_doc_from_user_data(user_to_index):
|
def create_doc_from_user_data(user_to_index):
|
||||||
doc_id = user_to_index['objectID']
|
doc_id = str(user_to_index['objectID'])
|
||||||
doc = User(_id=doc_id)
|
doc = User(_id=doc_id)
|
||||||
|
doc.objectID = str(user_to_index['objectID'])
|
||||||
|
doc.username = user_to_index['username']
|
||||||
|
doc.full_name = user_to_index['full_name']
|
||||||
|
doc.roles = list(map(str, user_to_index['roles']))
|
||||||
|
doc.groups = list(map(str, user_to_index['groups']))
|
||||||
|
doc.email = user_to_index['email']
|
||||||
return doc
|
return doc
|
||||||
|
|
||||||
|
|
||||||
@ -95,8 +116,10 @@ def create_doc_from_node_data(node_to_index):
|
|||||||
|
|
||||||
# node stuff
|
# node stuff
|
||||||
doc_id = str(node_to_index['objectID'])
|
doc_id = str(node_to_index['objectID'])
|
||||||
|
|
||||||
doc = Node(_id=doc_id)
|
doc = Node(_id=doc_id)
|
||||||
|
|
||||||
|
doc.objectID = str(node_to_index['objectID'])
|
||||||
doc.node_type = node_to_index['node_type']
|
doc.node_type = node_to_index['node_type']
|
||||||
doc.name = node_to_index['name']
|
doc.name = node_to_index['name']
|
||||||
doc.user.id = str(node_to_index['user']['_id'])
|
doc.user.id = str(node_to_index['user']['_id'])
|
||||||
@ -116,3 +139,20 @@ def create_doc_from_node_data(node_to_index):
|
|||||||
doc.updated_at = node_to_index['updated']
|
doc.updated_at = node_to_index['updated']
|
||||||
|
|
||||||
return doc
|
return doc
|
||||||
|
|
||||||
|
|
||||||
|
def create_doc_from_user(user_to_index: dict) -> User:
|
||||||
|
"""
|
||||||
|
Create a user document from user
|
||||||
|
"""
|
||||||
|
|
||||||
|
doc_id = str(user_to_index['objectID'])
|
||||||
|
doc = User(_id=doc_id)
|
||||||
|
doc.objectID = str(user_to_index['objectID'])
|
||||||
|
doc.full_name = user_to_index['full_name']
|
||||||
|
doc.username = user_to_index['username']
|
||||||
|
doc.roles = user_to_index['roles']
|
||||||
|
doc.groups = user_to_index['groups']
|
||||||
|
doc.email = user_to_index['email']
|
||||||
|
|
||||||
|
return doc
|
||||||
|
@ -26,6 +26,10 @@ def push_updated_user(user_to_index: dict):
|
|||||||
user_to_index.get('username'),
|
user_to_index.get('username'),
|
||||||
user_to_index.get('objectID'))
|
user_to_index.get('objectID'))
|
||||||
|
|
||||||
|
doc = documents.create_doc_from_user_data(user_to_index)
|
||||||
|
doc.save()
|
||||||
|
log.warning('CREATED ELK USER DOC')
|
||||||
|
|
||||||
|
|
||||||
def index_node_save(node_to_index: dict):
|
def index_node_save(node_to_index: dict):
|
||||||
|
|
||||||
@ -37,7 +41,7 @@ def index_node_save(node_to_index: dict):
|
|||||||
|
|
||||||
doc = documents.create_doc_from_node_data(node_to_index)
|
doc = documents.create_doc_from_node_data(node_to_index)
|
||||||
|
|
||||||
log.warning('CREATED ELK DOC')
|
log.warning('CREATED ELK NODE DOC')
|
||||||
doc.save()
|
doc.save()
|
||||||
|
|
||||||
|
|
||||||
|
@ -64,6 +64,21 @@ class ResetNodeIndex(ResetIndexTask):
|
|||||||
doc_types = [documents.Node]
|
doc_types = [documents.Node]
|
||||||
|
|
||||||
|
|
||||||
|
class ResetUserIndex(ResetIndexTask):
|
||||||
|
index = current_app.config['ELASTIC_INDICES']['USER']
|
||||||
|
doc_types = [documents.User]
|
||||||
|
|
||||||
|
|
||||||
def reset_node_index():
|
def reset_node_index():
|
||||||
resettask = ResetNodeIndex()
|
resettask = ResetNodeIndex()
|
||||||
resettask.execute()
|
resettask.execute()
|
||||||
|
|
||||||
|
|
||||||
|
def reset_index(indexnames):
|
||||||
|
if 'users' in indexnames:
|
||||||
|
resettask = ResetUserIndex()
|
||||||
|
resettask.execute()
|
||||||
|
if 'nodes' in indexnames:
|
||||||
|
resettask = ResetUserIndex()
|
||||||
|
resettask.execute()
|
||||||
|
|
||||||
|
@ -42,3 +42,44 @@ def do_search(query: str) -> dict:
|
|||||||
response = search.execute()
|
response = search.execute()
|
||||||
|
|
||||||
return response.to_dict()
|
return response.to_dict()
|
||||||
|
|
||||||
|
|
||||||
|
def do_user_search(query: str) -> dict:
|
||||||
|
"""
|
||||||
|
return user objects
|
||||||
|
"""
|
||||||
|
should = [
|
||||||
|
Q('match', username=query),
|
||||||
|
Q('match', full_name=query),
|
||||||
|
]
|
||||||
|
bool_query = Q('bool', should=should)
|
||||||
|
search = Search(using=client)
|
||||||
|
search.query = bool_query
|
||||||
|
|
||||||
|
if current_app.config['DEBUG']:
|
||||||
|
log.debug(json.dumps(search.to_dict(), indent=4))
|
||||||
|
|
||||||
|
response = search.execute()
|
||||||
|
|
||||||
|
return response.to_dict()
|
||||||
|
|
||||||
|
|
||||||
|
def do_user_search_admin(query: str) -> dict:
|
||||||
|
"""
|
||||||
|
return users with all fields and aggregations
|
||||||
|
"""
|
||||||
|
should = [
|
||||||
|
Q('match', username=query),
|
||||||
|
Q('match', email=query),
|
||||||
|
Q('match', full_name=query),
|
||||||
|
]
|
||||||
|
bool_query = Q('bool', should=should)
|
||||||
|
search = Search(using=client)
|
||||||
|
search.query = bool_query
|
||||||
|
|
||||||
|
if current_app.config['DEBUG']:
|
||||||
|
log.debug(json.dumps(search.to_dict(), indent=4))
|
||||||
|
|
||||||
|
response = search.execute()
|
||||||
|
|
||||||
|
return response.to_dict()
|
||||||
|
@ -18,16 +18,58 @@ blueprint_search = Blueprint('elksearch', __name__)
|
|||||||
|
|
||||||
from . import queries
|
from . import queries
|
||||||
|
|
||||||
#@authorization.require_login(require_cap='subscriber')
|
|
||||||
@blueprint_search.route('/', methods=['GET'])
|
def _valid_search() -> [str, str]:
|
||||||
def search_nodes():
|
"""
|
||||||
|
Validate search parameters
|
||||||
|
"""
|
||||||
|
|
||||||
searchword = request.args.get('q', '')
|
searchword = request.args.get('q', '')
|
||||||
|
|
||||||
if not searchword:
|
if not searchword:
|
||||||
return 'You are forgetting a "?q=whatareyoulookingfor"'
|
return '', 'You are forgetting a "?q=whatareyoulookingfor"'
|
||||||
|
|
||||||
|
return searchword, ''
|
||||||
|
|
||||||
|
|
||||||
|
@blueprint_search.route('/', methods=['GET'])
|
||||||
|
def search_nodes():
|
||||||
|
|
||||||
|
searchword, err = _valid_search()
|
||||||
|
if err:
|
||||||
|
return err
|
||||||
|
|
||||||
data = queries.do_search(searchword)
|
data = queries.do_search(searchword)
|
||||||
|
|
||||||
resp = Response(json.dumps(data), mimetype='application/json')
|
resp = Response(json.dumps(data), mimetype='application/json')
|
||||||
return resp
|
return resp
|
||||||
|
|
||||||
|
|
||||||
|
@blueprint_search.route('/user', methods=['GET'])
|
||||||
|
def search_user():
|
||||||
|
|
||||||
|
searchword, err = _valid_search()
|
||||||
|
if err:
|
||||||
|
return err
|
||||||
|
|
||||||
|
data = queries.do_user_search(searchword)
|
||||||
|
|
||||||
|
resp = Response(json.dumps(data), mimetype='application/json')
|
||||||
|
return resp
|
||||||
|
|
||||||
|
|
||||||
|
@authorization.require_login(require_cap='admin')
|
||||||
|
@blueprint_search.route('/admin/user', methods=['GET'])
|
||||||
|
def search_user_admin():
|
||||||
|
"""
|
||||||
|
User search over all fields.
|
||||||
|
"""
|
||||||
|
|
||||||
|
searchword, err = _valid_search()
|
||||||
|
if err:
|
||||||
|
return err
|
||||||
|
|
||||||
|
data = queries.do_user_search_admin(searchword)
|
||||||
|
|
||||||
|
resp = Response(json.dumps(data), mimetype='application/json')
|
||||||
|
return resp
|
||||||
|
@ -117,20 +117,23 @@ def prepare_node_data(node_id: str, node=None) -> dict:
|
|||||||
return to_index
|
return to_index
|
||||||
|
|
||||||
|
|
||||||
def prepare_user_data(user_id: str) -> dict:
|
def prepare_user_data(user_id: str, user=None) -> dict:
|
||||||
"""
|
"""
|
||||||
Prepare data to index for user node
|
Prepare data to index for user node
|
||||||
"""
|
"""
|
||||||
|
|
||||||
user_oid = ObjectId(user_id)
|
if not user:
|
||||||
log.info('Retrieving user %s', user_oid)
|
user_oid = ObjectId(user_id)
|
||||||
users_coll = current_app.db('users')
|
log.info('Retrieving user %s', user_oid)
|
||||||
user = users_coll.find_one({'_id': user_oid})
|
users_coll = current_app.db('users')
|
||||||
|
user = users_coll.find_one({'_id': user_oid})
|
||||||
|
|
||||||
if user is None:
|
if user is None:
|
||||||
log.warning('Unable to find user %s, not updating Algolia.', user_oid)
|
log.warning('Unable to find user %s, not updating Algolia.', user_oid)
|
||||||
return
|
return
|
||||||
|
|
||||||
user_roles = set(user.get('roles', ()))
|
user_roles = set(user.get('roles', ()))
|
||||||
|
|
||||||
if 'service' in user_roles:
|
if 'service' in user_roles:
|
||||||
return
|
return
|
||||||
|
|
||||||
|
@ -9,25 +9,49 @@ log = logging.getLogger(__name__)
|
|||||||
manager_elk = Manager(
|
manager_elk = Manager(
|
||||||
current_app, usage="Elastic utilities, like reset_index()")
|
current_app, usage="Elastic utilities, like reset_index()")
|
||||||
|
|
||||||
|
indexes = ['users', 'nodes']
|
||||||
|
|
||||||
|
|
||||||
@manager_elk.command
|
@manager_elk.command
|
||||||
def reset_index(elk_index):
|
def reset_index(elk_index=None):
|
||||||
"""
|
"""
|
||||||
Destroy and recreate elastic indices
|
Destroy and recreate elastic indices
|
||||||
|
|
||||||
node, user ...
|
node, user ...
|
||||||
"""
|
"""
|
||||||
#real_current_app = current_app._get_current_object()._get_current_object()
|
|
||||||
|
|
||||||
with current_app.app_context():
|
with current_app.app_context():
|
||||||
from pillar.api.search import index
|
from pillar.api.search import index
|
||||||
|
if not elk_index:
|
||||||
|
index.reset_index(indexes)
|
||||||
|
return
|
||||||
if elk_index == 'nodes':
|
if elk_index == 'nodes':
|
||||||
index.reset_node_index()
|
index.reset_index(['node'])
|
||||||
|
return
|
||||||
|
if elk_index == 'users':
|
||||||
|
index.reset_index(['user'])
|
||||||
|
return
|
||||||
|
|
||||||
|
|
||||||
@manager_elk.command
|
def _reindex_users():
|
||||||
def reindex_nodes():
|
db = current_app.db()
|
||||||
|
users_coll = db['users']
|
||||||
|
user_count = users_coll.count()
|
||||||
|
|
||||||
|
log.debug('Reindexing %d in Elastic', user_count)
|
||||||
|
|
||||||
|
from pillar.celery.search_index_tasks import prepare_user_data
|
||||||
|
from pillar.api.search import elastic_indexing
|
||||||
|
|
||||||
|
for user in users_coll.find():
|
||||||
|
to_index = prepare_user_data('', user=user)
|
||||||
|
if not to_index:
|
||||||
|
log.debug('missing user..')
|
||||||
|
continue
|
||||||
|
elastic_indexing.push_updated_user(to_index)
|
||||||
|
|
||||||
|
|
||||||
|
def _reindex_nodes():
|
||||||
db = current_app.db()
|
db = current_app.db()
|
||||||
nodes_coll = db['nodes']
|
nodes_coll = db['nodes']
|
||||||
node_count = nodes_coll.count()
|
node_count = nodes_coll.count()
|
||||||
@ -40,3 +64,17 @@ def reindex_nodes():
|
|||||||
for node in nodes_coll.find():
|
for node in nodes_coll.find():
|
||||||
to_index = prepare_node_data('', node=node)
|
to_index = prepare_node_data('', node=node)
|
||||||
elastic_indexing.index_node_save(to_index)
|
elastic_indexing.index_node_save(to_index)
|
||||||
|
|
||||||
|
|
||||||
|
@manager_elk.command
|
||||||
|
def reindex(indexname=None):
|
||||||
|
|
||||||
|
if not indexname:
|
||||||
|
log.debug('reindex everything..')
|
||||||
|
_reindex_nodes()
|
||||||
|
_reindex_users()
|
||||||
|
|
||||||
|
elif indexname == 'users':
|
||||||
|
_reindex_users()
|
||||||
|
elif indexname == 'nodes':
|
||||||
|
_reindex_nodes()
|
||||||
|
@ -30,7 +30,6 @@ $(document).ready(function() {
|
|||||||
var tu = searchInput.typeahead({hint: true}, {
|
var tu = searchInput.typeahead({hint: true}, {
|
||||||
//source: algoliaIndex.ttAdapter(),
|
//source: algoliaIndex.ttAdapter(),
|
||||||
source: elasticSearch(),
|
source: elasticSearch(),
|
||||||
//source: elkBlood(),
|
|
||||||
async: true,
|
async: true,
|
||||||
displayKey: 'name',
|
displayKey: 'name',
|
||||||
limit: 10,
|
limit: 10,
|
||||||
|
Loading…
x
Reference in New Issue
Block a user