Advanced query search syntax for multi byte search (#7546)

* Advanced query search syntax for multi byte search

* Advanced search for my queries

* Add advanced query seearch tooltip

* Revert "Add advanced query seearch tooltip"

This reverts commit 43148ba6ac.
This commit is contained in:
Tsuneo Yoshioka
2025-10-16 01:12:00 +09:00
committed by GitHub
parent c5aa5da6a2
commit bac2160e2a

View File

@@ -2,6 +2,7 @@ import calendar
import datetime import datetime
import logging import logging
import numbers import numbers
import re
import time import time
import pytz import pytz
@@ -644,6 +645,43 @@ class Query(ChangeTrackingMixin, TimestampMixin, BelongsToOrgMixin, db.Model):
return list(outdated_queries.values()) return list(outdated_queries.values())
@classmethod
def _do_multi_byte_search(cls, all_queries, term, limit=None):
# term examples:
# - word
# - name:word
# - query:word
# - "multiple words"
# - name:"multiple words"
# - word1 word2 word3
# - word1 "multiple word" query:"select foo"
tokens = re.findall(r'(?:([^:\s]+):)?(?:"([^"]+)"|(\S+))', term)
conditions = []
for token in tokens:
key = None
if token[0]:
key = token[0]
if token[1]:
value = token[1]
else:
value = token[2]
pattern = f"%{value}%"
if key == "id" and value.isdigit():
conditions.append(cls.id.equal(int(value)))
elif key == "name":
conditions.append(cls.name.ilike(pattern))
elif key == "query":
conditions.append(cls.query_text.ilike(pattern))
elif key == "description":
conditions.append(cls.description.ilike(pattern))
else:
conditions.append(or_(cls.name.ilike(pattern), cls.description.ilike(pattern)))
return all_queries.filter(and_(*conditions)).order_by(Query.id).limit(limit)
@classmethod @classmethod
def search( def search(
cls, cls,
@@ -664,12 +702,7 @@ class Query(ChangeTrackingMixin, TimestampMixin, BelongsToOrgMixin, db.Model):
if multi_byte_search: if multi_byte_search:
# Since tsvector doesn't work well with CJK languages, use `ilike` too # Since tsvector doesn't work well with CJK languages, use `ilike` too
pattern = "%{}%".format(term) return cls._do_multi_byte_search(all_queries, term, limit)
return (
all_queries.filter(or_(cls.name.ilike(pattern), cls.description.ilike(pattern)))
.order_by(Query.id)
.limit(limit)
)
# sort the result using the weight as defined in the search vector column # sort the result using the weight as defined in the search vector column
return all_queries.search(term, sort=True).limit(limit) return all_queries.search(term, sort=True).limit(limit)
@@ -678,13 +711,7 @@ class Query(ChangeTrackingMixin, TimestampMixin, BelongsToOrgMixin, db.Model):
def search_by_user(cls, term, user, limit=None, multi_byte_search=False): def search_by_user(cls, term, user, limit=None, multi_byte_search=False):
if multi_byte_search: if multi_byte_search:
# Since tsvector doesn't work well with CJK languages, use `ilike` too # Since tsvector doesn't work well with CJK languages, use `ilike` too
pattern = "%{}%".format(term) return cls._do_multi_byte_search(cls.by_user(user), term, limit)
return (
cls.by_user(user)
.filter(or_(cls.name.ilike(pattern), cls.description.ilike(pattern)))
.order_by(Query.id)
.limit(limit)
)
return cls.by_user(user).search(term, sort=True).limit(limit) return cls.by_user(user).search(term, sort=True).limit(limit)