feat: Basic Query + Autocomplete
This commit is contained in:
parent
0c47f3a876
commit
e82833f14a
@ -11,7 +11,12 @@ from erpnext.e_commerce.shopping_cart.product_info import set_product_info_for_w
|
|||||||
|
|
||||||
# For SEARCH -------
|
# For SEARCH -------
|
||||||
import redis
|
import redis
|
||||||
from redisearch import Client, AutoCompleter, Suggestion, IndexDefinition, TextField, TagField
|
from redisearch import (
|
||||||
|
Client, AutoCompleter, Query,
|
||||||
|
Suggestion, IndexDefinition,
|
||||||
|
TextField, TagField,
|
||||||
|
Document
|
||||||
|
)
|
||||||
|
|
||||||
WEBSITE_ITEM_INDEX = 'website_items_index'
|
WEBSITE_ITEM_INDEX = 'website_items_index'
|
||||||
WEBSITE_ITEM_KEY_PREFIX = 'website_item:'
|
WEBSITE_ITEM_KEY_PREFIX = 'website_item:'
|
||||||
@ -62,21 +67,46 @@ def get_product_list(search=None, start=0, limit=12):
|
|||||||
|
|
||||||
@frappe.whitelist(allow_guest=True)
|
@frappe.whitelist(allow_guest=True)
|
||||||
def search(query):
|
def search(query):
|
||||||
|
if not query:
|
||||||
|
# TODO: return top/recent searches
|
||||||
|
return []
|
||||||
|
|
||||||
ac = AutoCompleter(WEBSITE_ITEM_NAME_AUTOCOMPLETE, port=13000)
|
ac = AutoCompleter(WEBSITE_ITEM_NAME_AUTOCOMPLETE, port=13000)
|
||||||
|
client = Client(WEBSITE_ITEM_INDEX, port=13000)
|
||||||
suggestions = ac.get_suggestions(query, num=10)
|
suggestions = ac.get_suggestions(query, num=10)
|
||||||
print(suggestions)
|
|
||||||
return list([s.string for s in suggestions])
|
# Build a query
|
||||||
|
query_string = query
|
||||||
|
|
||||||
|
for s in suggestions:
|
||||||
|
query_string += f"|({s.string})"
|
||||||
|
|
||||||
|
q = Query(query_string)
|
||||||
|
|
||||||
|
print(f"Executing query: {q.query_string()}")
|
||||||
|
|
||||||
|
results = client.search(q)
|
||||||
|
results = list(map(convert_to_dict, results.docs))
|
||||||
|
|
||||||
|
print("SEARCH RESULTS ------------------\n ", results)
|
||||||
|
|
||||||
|
return results
|
||||||
|
|
||||||
|
def convert_to_dict(redis_search_doc):
|
||||||
|
return redis_search_doc.__dict__
|
||||||
|
|
||||||
def create_website_items_index():
|
def create_website_items_index():
|
||||||
'''Creates Index Definition'''
|
'''Creates Index Definition'''
|
||||||
|
# CREATE index
|
||||||
|
client = Client(WEBSITE_ITEM_INDEX, port=13000)
|
||||||
|
|
||||||
# DROP if already exists
|
# DROP if already exists
|
||||||
try:
|
try:
|
||||||
client.drop_index()
|
client.drop_index()
|
||||||
except:
|
except:
|
||||||
pass
|
pass
|
||||||
|
|
||||||
# CREATE index
|
|
||||||
client = Client(WEBSITE_ITEM_INDEX, port=13000)
|
|
||||||
idx_def = IndexDefinition([WEBSITE_ITEM_KEY_PREFIX])
|
idx_def = IndexDefinition([WEBSITE_ITEM_KEY_PREFIX])
|
||||||
|
|
||||||
client.create_index(
|
client.create_index(
|
||||||
@ -92,11 +122,11 @@ def insert_item_to_index(website_item_doc):
|
|||||||
r = redis.Redis("localhost", 13000)
|
r = redis.Redis("localhost", 13000)
|
||||||
web_item = create_web_item_map(website_item_doc)
|
web_item = create_web_item_map(website_item_doc)
|
||||||
r.hset(key, mapping=web_item)
|
r.hset(key, mapping=web_item)
|
||||||
insert_to_name_ac(website_item_doc.name)
|
insert_to_name_ac(website_item_doc.web_item_name, website_item_doc.name)
|
||||||
|
|
||||||
def insert_to_name_ac(name):
|
def insert_to_name_ac(web_name, doc_name):
|
||||||
ac = AutoCompleter(WEBSITE_ITEM_NAME_AUTOCOMPLETE, port=13000)
|
ac = AutoCompleter(WEBSITE_ITEM_NAME_AUTOCOMPLETE, port=13000)
|
||||||
ac.add_suggestions(Suggestion(name))
|
ac.add_suggestions(Suggestion(web_name, payload=doc_name))
|
||||||
|
|
||||||
def create_web_item_map(website_item_doc):
|
def create_web_item_map(website_item_doc):
|
||||||
web_item = {}
|
web_item = {}
|
||||||
@ -169,5 +199,6 @@ def get_cache_key(name):
|
|||||||
return f"{WEBSITE_ITEM_KEY_PREFIX}{name}"
|
return f"{WEBSITE_ITEM_KEY_PREFIX}{name}"
|
||||||
|
|
||||||
# TODO: Remove later
|
# TODO: Remove later
|
||||||
|
# Figure out a way to run this at startup
|
||||||
define_autocomplete_dictionary()
|
define_autocomplete_dictionary()
|
||||||
create_website_items_index()
|
create_website_items_index()
|
||||||
|
|||||||
5
erpnext/www/all-products/search.css
Normal file
5
erpnext/www/all-products/search.css
Normal file
@ -0,0 +1,5 @@
|
|||||||
|
.item-thumb {
|
||||||
|
height: 50px;
|
||||||
|
width: 50px;
|
||||||
|
object-fit: cover;
|
||||||
|
}
|
||||||
@ -1,7 +1,11 @@
|
|||||||
{% extends "templates/web.html" %}
|
{% extends "templates/web.html" %}
|
||||||
|
|
||||||
|
|
||||||
{% block title %}{{ _('Search') }}{% endblock %}
|
{% block title %}{{ _('Search') }}{% endblock %}
|
||||||
|
|
||||||
|
{%- block head_include %}
|
||||||
|
<link rel="stylesheet" href="search.css">
|
||||||
|
{% endblock -%}
|
||||||
|
|
||||||
{% block header %}
|
{% block header %}
|
||||||
<div class="mb-6">{{ _('Search Products') }}</div>
|
<div class="mb-6">{{ _('Search Products') }}</div>
|
||||||
{% endblock header %}
|
{% endblock header %}
|
||||||
|
|||||||
@ -1,12 +1,16 @@
|
|||||||
console.log("search.js loaded");
|
console.log("search.js reloaded");
|
||||||
|
|
||||||
const search_box = document.getElementById("search-box");
|
const search_box = document.getElementById("search-box");
|
||||||
const results = document.getElementById("results");
|
const results = document.getElementById("results");
|
||||||
|
|
||||||
function populateResults(data) {
|
function populateResults(data) {
|
||||||
|
console.log(data);
|
||||||
html = ""
|
html = ""
|
||||||
for (let res of data.message) {
|
for (let res of data.message) {
|
||||||
html += `<li>${res}</li>`
|
html += `<li>
|
||||||
|
<img class="item-thumb" src="${res.thumbnail || ''}" />
|
||||||
|
<a href="/${res.route}">${res.web_item_name}</a>
|
||||||
|
</li>`
|
||||||
}
|
}
|
||||||
console.log(html);
|
console.log(html);
|
||||||
results.innerHTML = html;
|
results.innerHTML = html;
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user