knowledgebase: include the topic (application name) in list search
The KB list search matched only shortdescription + keywords, so searching a topic (e.g. "Spotfire", the Application name) surfaced just the one article whose title/keywords contained the word, not the others tied to it by topic. Match the topic too via an appid IN (apps named like the term) subquery - used instead of a join so it does not collide with the sort=topic join, and articles with no app still match on title/keywords.
This commit is contained in:
@@ -29,12 +29,19 @@ def list_articles():
|
|||||||
|
|
||||||
query = KnowledgeBase.query.filter_by(isactive=True)
|
query = KnowledgeBase.query.filter_by(isactive=True)
|
||||||
|
|
||||||
# Search
|
# Search: title, keywords, and the topic (its Application's name). The topic
|
||||||
|
# is matched via an appid subquery instead of a join so it does not collide
|
||||||
|
# with the sort=='topic' join below; articles with no app just miss that
|
||||||
|
# clause and still match on title/keywords.
|
||||||
if search := request.args.get('search'):
|
if search := request.args.get('search'):
|
||||||
|
like = f'%{search}%'
|
||||||
|
topic_appids = db.session.query(Application.appid).filter(
|
||||||
|
Application.appname.ilike(like))
|
||||||
query = query.filter(
|
query = query.filter(
|
||||||
db.or_(
|
db.or_(
|
||||||
KnowledgeBase.shortdescription.ilike(f'%{search}%'),
|
KnowledgeBase.shortdescription.ilike(like),
|
||||||
KnowledgeBase.keywords.ilike(f'%{search}%')
|
KnowledgeBase.keywords.ilike(like),
|
||||||
|
KnowledgeBase.appid.in_(topic_appids)
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|||||||
@@ -32,3 +32,36 @@ def test_create_requires_shortdescription(client, db, auth_headers):
|
|||||||
json={'linkurl': 'https://kb.example/x'},
|
json={'linkurl': 'https://kb.example/x'},
|
||||||
headers=auth_headers)
|
headers=auth_headers)
|
||||||
assert resp.status_code == 400
|
assert resp.status_code == 400
|
||||||
|
|
||||||
|
|
||||||
|
def test_search_matches_topic_appname(client, db, auth_headers):
|
||||||
|
"""Searching a topic (Application name) returns every article under it, not
|
||||||
|
just the one whose title/keywords happen to contain the word.
|
||||||
|
|
||||||
|
Regression: KB list search omitted the topic, so a topic-only match (e.g.
|
||||||
|
'Spotfire' as the app) surfaced a single article instead of all of them.
|
||||||
|
"""
|
||||||
|
from shopdb.core.models import Application
|
||||||
|
|
||||||
|
app_row = Application(appname='Spotfire')
|
||||||
|
db.session.add(app_row)
|
||||||
|
db.session.flush()
|
||||||
|
|
||||||
|
# Two articles whose title/keywords do NOT contain 'Spotfire' - only the
|
||||||
|
# topic (appid) ties them to it - plus one that does mention it directly.
|
||||||
|
for payload in [
|
||||||
|
{'shortdescription': 'Dashboard login steps', 'keywords': 'login',
|
||||||
|
'linkurl': 'https://kb.example/a', 'appid': app_row.appid},
|
||||||
|
{'shortdescription': 'Export a visualization', 'keywords': 'export',
|
||||||
|
'linkurl': 'https://kb.example/b', 'appid': app_row.appid},
|
||||||
|
{'shortdescription': 'Spotfire install guide', 'keywords': 'install',
|
||||||
|
'linkurl': 'https://kb.example/c', 'appid': app_row.appid},
|
||||||
|
]:
|
||||||
|
resp = client.post('/api/knowledgebase', json=payload, headers=auth_headers)
|
||||||
|
assert resp.status_code == 201, resp.get_json()
|
||||||
|
|
||||||
|
listing = client.get('/api/knowledgebase?search=Spotfire', headers=auth_headers)
|
||||||
|
assert listing.status_code == 200
|
||||||
|
urls = {a['linkurl'] for a in listing.get_json()['data']}
|
||||||
|
assert {'https://kb.example/a', 'https://kb.example/b',
|
||||||
|
'https://kb.example/c'} <= urls
|
||||||
|
|||||||
Reference in New Issue
Block a user