search is completely working in frontend now

This commit is contained in:
Stephan preeker 2017-12-01 16:32:57 +01:00
parent b0d6f724ef
commit 1cba014948
6 changed files with 105 additions and 58 deletions

View File

@ -2,33 +2,57 @@ import logging
import json
from elasticsearch import Elasticsearch
from elasticsearch_dsl import Search, Q
from elasticsearch_dsl.connections import connections
from pillar import current_app
#elk_hosts = current_app.config['ELASTIC_SEARCH_HOSTS']
#
#connections.create_connection(
# hosts=elk_hosts,
# sniff_on_start=True,
# timeout=20)
#
client = Elasticsearch()
log = logging.getLogger(__name__)
node_agg_terms = ['node_type', 'media', 'tags', 'is_free']
user_agg_terms = ['roles', ]
def add_aggs_to_search(search):
def add_aggs_to_search(search, agg_terms):
"""
Add facets / aggregations to the search result
"""
agg_terms = ['node_type', 'media', 'tags', 'is_free']
for term in agg_terms:
search.aggs.bucket(term, 'terms', field=term)
#search.aggs.bucket('project', 'terms', field='project.name')
def make_must(terms):
"""
Given some term parameters
we must match those
"""
must = []
for field, value in terms.items():
print(field, value)
if value:
must.append({'match': {field: value}})
return must
def nested_bool(should, terms):
"""
"""
must = []
must = make_must(terms)
bool_query = Q('bool', should=should)
must.append(bool_query)
bool_query = Q('bool', must=must)
search = Search(using=client)
search.query = bool_query
return search
def do_search(query: str, terms: dict) -> dict:
@ -46,16 +70,14 @@ def do_search(query: str, terms: dict) -> dict:
Q('term', tags=query),
]
#must = []
#for field, value in terms.items():
# must.append(
bool_query = Q('bool', should=should)
if query:
search = nested_bool(should, terms)
else:
# do a match all for the aggregations
search = Search(using=client)
search.query = bool_query
search.query = Q('term', _type='node')
add_aggs_to_search(search)
add_aggs_to_search(search, node_agg_terms)
if current_app.config['DEBUG']:
print(json.dumps(search.to_dict(), indent=4))
@ -68,7 +90,7 @@ def do_search(query: str, terms: dict) -> dict:
return response.to_dict()
def do_user_search(query: str) -> dict:
def do_user_search(query: str, terms: dict) -> dict:
"""
return user objects
"""
@ -76,17 +98,23 @@ def do_user_search(query: str) -> dict:
Q('match', username=query),
Q('match', full_name=query),
]
bool_query = Q('bool', should=should)
if query:
search = nested_bool(should, terms)
else:
# do a match all for the aggregations
search = Search(using=client)
search.query = bool_query
search.query = Q('term', _type='user')
add_aggs_to_search(search, user_agg_terms)
if current_app.config['DEBUG']:
log.debug(json.dumps(search.to_dict(), indent=4))
print(json.dumps(search.to_dict(), indent=4))
response = search.execute()
if current_app.config['DEBUG']:
log.debug('%s', json.dumps(response.to_dict(), indent=4))
print(json.dumps(response.to_dict(), indent=4))
return response.to_dict()

View File

@ -1,22 +1,15 @@
import json
import logging
from bson import ObjectId
from flask import Blueprint, request, current_app, make_response, url_for
from flask import Response
from flask import Blueprint, request
from werkzeug import exceptions as wz_exceptions
from pillar.api.utils import authorization, jsonify
from pillar.api.utils import authorization, jsonify, str2id
from pillar.api.utils import mongo
from pillar.api.utils.authorization import require_login, check_permissions
from pillar.auth import current_user
from . import queries
log = logging.getLogger(__name__)
blueprint_search = Blueprint('elksearch', __name__)
from . import queries
def _valid_search() -> str:
@ -25,19 +18,23 @@ def _valid_search() -> str:
"""
searchword = request.args.get('q', '')
if not searchword:
raise wz_exceptions.BadRequest('You are forgetting a "?q=whatareyoulookingfor"')
# if not searchword:
# raise wz_exceptions.BadRequest(
# 'You are forgetting a "?q=whatareyoulookingfor"')
return searchword
def _term_filters() -> dict:
"""
Check if frontent want to filter stuff
Check if frontent wants to filter stuff
on specific fields AKA facets
"""
terms = [
'node_type', 'media',
'tags', 'is_free', 'projectname']
'tags', 'is_free', 'projectname',
'roles',
]
parsed_terms = {}
@ -60,7 +57,8 @@ def search_user():
searchword = _valid_search()
data = queries.do_user_search(searchword)
terms = _term_filters()
data = queries.do_user_search(searchword, terms)
return jsonify(data)

View File

@ -8,7 +8,9 @@ $(document).ready(function() {
var $hits = $('#hits');
var $stats = $('#stats');
var $facets = $('#facets');
//var facets = [];
var $pagination = $('#pagination');
var what = '';
// Templates binding
var hitTemplate = Hogan.compile($('#hit-template').text());
@ -19,6 +21,7 @@ $(document).ready(function() {
// something elasticy!
var search = elasticSearcher;
// facets: $.map(FACET_CONFIG, function(facet) {
// return !facet.disjunctive ? facet.name : null;
// }),
@ -137,17 +140,23 @@ $(document).ready(function() {
// If no results
if (content.hits.length === 0) {
$facets.empty();
facets =[];
return;
}
var storeValue = function (values, label){
return function(item){
let refined = search.isRefined(label, item.key);
values.push({
facet: label,
label: item.key,
value: item.key,
count: item.doc_count,
refined: refined,
});
};
};
@ -164,6 +173,8 @@ $(document).ready(function() {
if (buckets.length === 0) { continue; }
buckets.forEach(storeValue(values, label));
facets.push({
@ -252,7 +263,7 @@ $(document).ready(function() {
});
$(document).on('click', '.toggleRefine', function() {
search.addTerm($(this).data('facet'), $(this).data('value'));
search.toggleTerm($(this).data('facet'), $(this).data('value'));
search.execute();
return false;
});
@ -277,6 +288,7 @@ $(document).ready(function() {
$('#facets').on("mouseenter mouseleave", ".button-checkbox", function(e) {
$(this).parent().find('.facet_link').toggleClass("hover");
});
$('#facets').on("mouseenter mouseleave", ".facet_link", function(e) {
$(this).parent().find('.button-checkbox button.btn').toggleClass("hover");
});
@ -330,7 +342,7 @@ $(document).ready(function() {
}
var query = decodeURIComponent(sURLVariables[0].split('=')[1]);
$inputField.val(query);
search.setQuery(query);
search.setQuery(query, what);
for (var i = 2; i < sURLVariables.length; i++) {
var sParameterName = sURLVariables[i].split('=');
@ -362,4 +374,8 @@ $(document).ready(function() {
location.replace(urlParams);
}
// do empty search to fill aggregations
search.setQuery('', what);
search.execute();
});

View File

@ -14,7 +14,7 @@ var elasticSearcher = (function() {
page: 0,
setQuery: (function(q, _url){
console.log('setQuery!: ' + q);
console.log('setQuery!: ' + q + 'what :'+ _url);
deze.query=q;
if (_url !== undefined) {
deze.url=_url;
@ -45,8 +45,19 @@ var elasticSearcher = (function() {
return deze.newhits.aggregations;
}),
addTerm: (function(term, value){
toggleTerm: (function(term, value){
if (deze.terms[term] !== undefined) {
delete deze.terms[term];
} else {
deze.terms[term] = value;
}
}),
isRefined: (function(term, value){
if (deze.terms[term] === value) {
return true;
}
return false;
}),
//get response from elastic and rebuild json
@ -89,7 +100,8 @@ var elasticSearcher = (function() {
setCurrentPage: deze.setCurrentPage,
query: deze.query,
page: deze.page,
addTerm: deze.addTerm,
toggleTerm: deze.toggleTerm,
isRefined: deze.isRefined,
};
})();

View File

@ -22,6 +22,7 @@ style.
type="text",
name="q",
id="q",
what="/user",
autocomplete="off",
spellcheck="false",
autocorrect="false",
@ -92,14 +93,6 @@ script(type="text/template", id="stats-template")
| {% endblock %}
| {% block footer_scripts %}
script().
var APPLICATION_ID = '{{config.ALGOLIA_USER}}';
var SEARCH_ONLY_API_KEY = '{{config.ALGOLIA_PUBLIC_KEY}}';
var INDEX_NAME = '{{config.ALGOLIA_INDEX_USERS}}';
var sortByCountDesc = null;
var FACET_CONFIG = [
{ name: 'roles', title: 'Roles', disjunctive: false, sortFunction: sortByCountDesc },
];
script(src="{{ url_for('static_pillar', filename='assets/js/vendor/algoliasearch-3.19.0.min.js')}}")
script(src="{{ url_for('static_pillar', filename='assets/js/vendor/algoliasearch.helper.min.js') }}")