Skip to content

Commit 15e100d

Browse files
committed
Improve dashboard_services search relevance
i have improved the dashboard_services engine by implementing a weighted scoring system to filter and rank services based on query relevance. This includes matches in name, description, server, container, and group. Additionally, we have added support for displaying service icons in results and refactored the code for better clarity and maintainability. Update dashboard_services.py
1 parent 12b02b0 commit 15e100d

File tree

1 file changed

+83
-17
lines changed

1 file changed

+83
-17
lines changed

python/searxng-addons/dashboard_services.py

Lines changed: 83 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,6 @@
77
1. Copy file to `/usr/local/searxng/searx/engines/dashboard_services.py`
88
2. Add the following configuration to your `settings.yml` file:
99
10-
```yaml
1110
engines:
1211
- name: selfhosted
1312
engine: dashboard_services
@@ -18,13 +17,11 @@
1817
enable_http: true
1918
enable_http2: true
2019
weight: 0.5 # Higher priority than regular search engines
21-
```
2220
2321
For use with https://github.com/searxng/searxng
2422
"""
2523

2624
from json import loads
27-
from searx.result_types import EngineResults
2825

2926
# Point to your self-hosted homepage instance
3027
HOMEPAGE_BASE_URL = "http://X.X.X.X:3000"
@@ -50,9 +47,15 @@
5047
# API endpoint
5148
base_url = f"{HOMEPAGE_BASE_URL}/api/services"
5249

50+
# Store the current query
51+
_current_query = ""
52+
5353

5454
def request(query, params):
5555
"""Build the request parameters for the dashboard services API."""
56+
global _current_query
57+
_current_query = query.lower() # Store for filtering in response
58+
5659
params["url"] = base_url
5760
params["method"] = "GET"
5861
params["headers"] = {
@@ -62,9 +65,10 @@ def request(query, params):
6265
return params
6366

6467

65-
def response(resp) -> EngineResults:
68+
def response(resp):
6669
"""Parse the API response and return search results."""
67-
results = EngineResults()
70+
global _current_query
71+
results = []
6872

6973
try:
7074
# Check if response is empty
@@ -75,11 +79,14 @@ def response(resp) -> EngineResults:
7579
# Parse JSON response
7680
json_data = loads(resp.text)
7781

78-
# Get query from the original request (simplified)
79-
query = ""
80-
if hasattr(resp, "url") and "?" in str(resp.url):
81-
# Try to extract query from URL params if available
82-
pass
82+
# Get the query for filtering
83+
query = _current_query
84+
if not query:
85+
print("Dashboard Services Engine: No query available")
86+
return results # No query, no results
87+
88+
# Collect all matching services with their scores
89+
matched_services = []
8390

8491
# Process each group in the response
8592
for group in json_data:
@@ -88,19 +95,42 @@ def response(resp) -> EngineResults:
8895
# Process direct services
8996
if "services" in group:
9097
for service in group["services"]:
91-
results.append(_create_service_result(service, group_name))
98+
score = _calculate_match_score(service, group_name, query)
99+
if score > 0: # Only include if there's a match
100+
matched_services.append(
101+
{
102+
"service": service,
103+
"group_name": group_name,
104+
"score": score,
105+
}
106+
)
92107

93108
# Process nested groups
94109
if "groups" in group:
95110
for subgroup in group["groups"]:
96111
subgroup_name = subgroup.get("name", "Unknown Subgroup")
97112
if "services" in subgroup:
98113
for service in subgroup["services"]:
99-
results.append(
100-
_create_service_result(
101-
service, f"{group_name} > {subgroup_name}"
102-
)
114+
score = _calculate_match_score(
115+
service, f"{group_name} > {subgroup_name}", query
103116
)
117+
if score > 0: # Only include if there's a match
118+
matched_services.append(
119+
{
120+
"service": service,
121+
"group_name": f"{group_name} > {subgroup_name}",
122+
"score": score,
123+
}
124+
)
125+
126+
# Sort by score (highest first)
127+
matched_services.sort(key=lambda x: x["score"], reverse=True)
128+
129+
# Create results from sorted matches
130+
for match in matched_services:
131+
results.append(
132+
_create_service_result(match["service"], match["group_name"])
133+
)
104134

105135
except Exception as e:
106136
print(f"Dashboard Services Engine Error: {e}")
@@ -111,13 +141,40 @@ def response(resp) -> EngineResults:
111141
return results
112142

113143

144+
def _calculate_match_score(service, group_name, query):
145+
"""Calculate a relevance score based on where the query matches."""
146+
score = 0
147+
148+
# Get the values to check, converting to lowercase and handling None values
149+
name = (service.get("name", "") or "").lower()
150+
description = (service.get("description", "") or "").lower()
151+
server = (service.get("server", "") or "").lower()
152+
container = (service.get("container", "") or "").lower()
153+
group_name = (group_name or "").lower()
154+
155+
# Check for matches in different fields with different weights
156+
if query in name:
157+
score += 10 # Highest weight for name match
158+
if query in description:
159+
score += 5 # Medium weight for description match
160+
if query in server:
161+
score += 2 # Lower weight for server/container matches
162+
if query in container:
163+
score += 2
164+
if query in group_name:
165+
score += 3 # Medium-low weight for group match
166+
167+
return score
168+
169+
114170
def _create_service_result(service, group_name):
115171
"""Create a search result from a service object."""
116172
name = service.get("name", "Unknown Service")
117173
description = service.get("description", "No description available")
118174
href = service.get("href", "#")
119175
server = service.get("server", "")
120176
container = service.get("container", "")
177+
icon = service.get("icon", "")
121178

122179
# Simple content creation
123180
content = description
@@ -126,9 +183,18 @@ def _create_service_result(service, group_name):
126183
if container:
127184
content += f" | Container: {container}"
128185

129-
return {
186+
result = {
130187
"url": href,
131188
"title": f"{name} ({group_name})",
132189
"content": content,
133-
"category": "dashboard_services",
134190
}
191+
192+
# Add icon if available
193+
if icon:
194+
if icon.startswith("http"):
195+
result["img_src"] = icon
196+
elif icon.startswith("/"):
197+
# Local icon path
198+
result["img_src"] = f"{HOMEPAGE_BASE_URL}{icon}"
199+
200+
return result

0 commit comments

Comments
 (0)