Skip to content

Commit

Permalink
CO-3781 Proper fix for keeping similarity ordering with fuzzy search
Browse files Browse the repository at this point in the history
  • Loading branch information
ecino committed Sep 16, 2021
1 parent 2639f12 commit b5a325a
Showing 1 changed file with 41 additions and 0 deletions.
41 changes: 41 additions & 0 deletions partner_compassion/models/partner_compassion.py
Original file line number Diff line number Diff line change
Expand Up @@ -11,8 +11,10 @@
import tempfile
import uuid
import base64
import re

from odoo import api, registry, fields, models, _
from odoo.exceptions import UserError
from odoo.tools import mod10r
from odoo.tools.config import config

Expand All @@ -38,6 +40,7 @@

logger = logging.getLogger(__name__)
MAGIC_INSTALLED = False
regex_order = re.compile('^similarity\((.*),.*\)(\s+(desc|asc))?$', re.I)

try:
import magic
Expand Down Expand Up @@ -421,6 +424,7 @@ def name_search(self, name, args=None, operator="ilike", limit=80):
if not res:
res = self.search(
["|", ("name", "%", name), ("name", "ilike", name)],
order="similarity(name, '%s') DESC" % name,
limit=limit,
)
# Search by e-mail
Expand All @@ -430,6 +434,43 @@ def name_search(self, name, args=None, operator="ilike", limit=80):
res = self.search(args, limit=limit)
return res.name_get()

@api.model
def search(self, args, offset=0, limit=None, order=None, count=False):
""" Order search results based on similarity if name search is used."""
fuzzy_search = False
for arg in args:
if arg[0] == "name" and arg[1] == "%":
fuzzy_search = arg[2]
break
if fuzzy_search:
order = self.env.cr.mogrify(
"similarity(res_partner.name, %s) DESC", [fuzzy_search]
)
if order and isinstance(order, bytes):
order = order.decode("utf-8")
return super().search(args, offset, limit, order, count)

@api.model
def _generate_order_by_inner(self, alias, order_spec, query,
reverse_direction=False, seen=None):
# Small trick to allow similarity ordering while bypassing odoo checks
is_similarity_ordering = regex_order.match(order_spec) if order_spec else False
if is_similarity_ordering:
order_by_elements = [order_spec]
else:
order_by_elements = super()._generate_order_by_inner(
alias, order_spec, query, reverse_direction, seen)
return order_by_elements

def _check_qorder(self, word):
""" Allow similarity order """
try:
super()._check_qorder(word)
except UserError:
if not regex_order.match(word):
raise
return True

##########################################################################
# ONCHANGE METHODS #
##########################################################################
Expand Down

0 comments on commit b5a325a

Please sign in to comment.