implement fulltext search keyword
This commit is contained in:
parent
eb5a7338ab
commit
e4dd47aed0
|
@ -136,6 +136,11 @@ class SearchHandler:
|
||||||
date_str = datetime.strftime(date_refresh, "%d %b, %Y")
|
date_str = datetime.strftime(date_refresh, "%d %b, %Y")
|
||||||
hit["source"]["channel"]["channel_last_refresh"] = date_str
|
hit["source"]["channel"]["channel_last_refresh"] = date_str
|
||||||
|
|
||||||
|
if "subtitle_fragment_id" in hit_keys:
|
||||||
|
youtube_id = hit["source"]["youtube_id"]
|
||||||
|
thumb_path = ThumbManager().vid_thumb_path(youtube_id)
|
||||||
|
hit["source"]["vid_thumb_url"] = f"/cache/{thumb_path}"
|
||||||
|
|
||||||
return hit
|
return hit
|
||||||
|
|
||||||
|
|
||||||
|
@ -159,6 +164,7 @@ class SearchForm:
|
||||||
video_results = []
|
video_results = []
|
||||||
channel_results = []
|
channel_results = []
|
||||||
playlist_results = []
|
playlist_results = []
|
||||||
|
fulltext_results = []
|
||||||
if search_results:
|
if search_results:
|
||||||
for result in search_results:
|
for result in search_results:
|
||||||
if result["_index"] == "ta_video":
|
if result["_index"] == "ta_video":
|
||||||
|
@ -167,11 +173,14 @@ class SearchForm:
|
||||||
channel_results.append(result)
|
channel_results.append(result)
|
||||||
elif result["_index"] == "ta_playlist":
|
elif result["_index"] == "ta_playlist":
|
||||||
playlist_results.append(result)
|
playlist_results.append(result)
|
||||||
|
elif result["_index"] == "ta_subtitle":
|
||||||
|
fulltext_results.append(result)
|
||||||
|
|
||||||
all_results = {
|
all_results = {
|
||||||
"video_results": video_results,
|
"video_results": video_results,
|
||||||
"channel_results": channel_results,
|
"channel_results": channel_results,
|
||||||
"playlist_results": playlist_results,
|
"playlist_results": playlist_results,
|
||||||
|
"fulltext_results": fulltext_results,
|
||||||
}
|
}
|
||||||
|
|
||||||
return all_results
|
return all_results
|
||||||
|
@ -240,7 +249,7 @@ class SearchParser:
|
||||||
"active": [],
|
"active": [],
|
||||||
"subscribed": [],
|
"subscribed": [],
|
||||||
},
|
},
|
||||||
"all": {
|
"full": {
|
||||||
"index": "ta_subtitle",
|
"index": "ta_subtitle",
|
||||||
"term": [],
|
"term": [],
|
||||||
},
|
},
|
||||||
|
@ -303,11 +312,18 @@ class QueryBuilder:
|
||||||
"video": self._build_video,
|
"video": self._build_video,
|
||||||
"channel": self._build_channel,
|
"channel": self._build_channel,
|
||||||
"playlist": self._build_playlist,
|
"playlist": self._build_playlist,
|
||||||
|
"full": self._build_fulltext,
|
||||||
}
|
}
|
||||||
|
|
||||||
build_must_list = exec_map[self.query_type]
|
build_must_list = exec_map[self.query_type]
|
||||||
|
|
||||||
query = {"size": 30, "query": {"bool": {"must": build_must_list()}}}
|
if self.query_type == "full":
|
||||||
|
query = build_must_list()
|
||||||
|
else:
|
||||||
|
query = {
|
||||||
|
"size": 30,
|
||||||
|
"query": {"bool": {"must": build_must_list()}},
|
||||||
|
}
|
||||||
|
|
||||||
return query
|
return query
|
||||||
|
|
||||||
|
@ -448,3 +464,36 @@ class QueryBuilder:
|
||||||
)
|
)
|
||||||
|
|
||||||
return must_list
|
return must_list
|
||||||
|
|
||||||
|
def _build_fulltext(self):
|
||||||
|
"""build query for fulltext search"""
|
||||||
|
must_list = []
|
||||||
|
|
||||||
|
if (term := self.query_map.get("term")) is not None:
|
||||||
|
must_list.append(
|
||||||
|
{
|
||||||
|
"match": {
|
||||||
|
"subtitle_line": {
|
||||||
|
"query": term,
|
||||||
|
"fuzziness": "auto",
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
)
|
||||||
|
|
||||||
|
query = {
|
||||||
|
"size": 30,
|
||||||
|
"_source": {"excludes": "subtitle_line"},
|
||||||
|
"query": {"bool": {"must": must_list}},
|
||||||
|
"highlight": {
|
||||||
|
"fields": {
|
||||||
|
"subtitle_line": {
|
||||||
|
"number_of_fragments": 0,
|
||||||
|
"pre_tags": ['<span class="settings-current">'],
|
||||||
|
"post_tags": ["</span>"],
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
return query
|
||||||
|
|
|
@ -26,5 +26,11 @@
|
||||||
<p>No playlists found.</p>
|
<p>No playlists found.</p>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
<div class="multi-search-result">
|
||||||
|
<h2>Fulltext Results</h2>
|
||||||
|
<div id="fulltext-results" class="video-list list">
|
||||||
|
<p>No fulltext results found.</p>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
{% endblock content %}
|
{% endblock content %}
|
||||||
|
|
|
@ -781,6 +781,10 @@ button:hover {
|
||||||
}
|
}
|
||||||
|
|
||||||
/* multi search page */
|
/* multi search page */
|
||||||
|
.multi-search-box {
|
||||||
|
padding-right: 20px;
|
||||||
|
}
|
||||||
|
|
||||||
.multi-search-box input {
|
.multi-search-box input {
|
||||||
width: 100%;
|
width: 100%;
|
||||||
}
|
}
|
||||||
|
|
|
@ -869,6 +869,24 @@ function populateMultiSearchResults(allResults, queryType) {
|
||||||
playlistBox.parentElement.style.display = "none";
|
playlistBox.parentElement.style.display = "none";
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
// fulltext
|
||||||
|
var allFullText = allResults.fulltext_results;
|
||||||
|
var fullTextBox = document.getElementById("fulltext-results");
|
||||||
|
fullTextBox.innerHTML = "";
|
||||||
|
fullTextBox.parentElement.style.display = "block";
|
||||||
|
if (allFullText.length > 0) {
|
||||||
|
for (let i = 0; i < allFullText.length; i++) {
|
||||||
|
const fullText = allFullText[i];
|
||||||
|
const fullTextDiv = createFulltext(fullText);
|
||||||
|
fullTextBox.appendChild(fullTextDiv);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
if (queryType === "simple" || queryType == "full") {
|
||||||
|
fullTextBox.innerHTML = "<p>No fulltext items found.</p>";
|
||||||
|
} else {
|
||||||
|
fullTextBox.parentElement.style.display = "none";
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -992,6 +1010,40 @@ function createPlaylist(playlist, viewStyle) {
|
||||||
return playlistDiv;
|
return playlistDiv;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function createFulltext(fullText) {
|
||||||
|
const videoId = fullText.source.youtube_id;
|
||||||
|
const videoTitle = fullText.source.title;
|
||||||
|
const thumbUrl = fullText.source.vid_thumb_url;
|
||||||
|
const channelId = fullText.source.subtitle_channel_id;
|
||||||
|
const channelName = fullText.source.subtitle_channel;
|
||||||
|
const subtitleLine = fullText.highlight.subtitle_line[0];
|
||||||
|
const subtitle_start = fullText.source.subtitle_start.split(".")[0];
|
||||||
|
const subtitle_end = fullText.source.subtitle_end.split(".")[0];
|
||||||
|
const markup = `
|
||||||
|
<a href="#player" data-id="${videoId}" onclick="createPlayer(this)">
|
||||||
|
<div class="video-thumb-wrap list">
|
||||||
|
<div class="video-thumb">
|
||||||
|
<img src="${thumbUrl}" alt="video-thumb">
|
||||||
|
</div>
|
||||||
|
<div class="video-play">
|
||||||
|
<img src="/static/img/icon-play.svg" alt="play-icon">
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</a>
|
||||||
|
<div class="video-desc list">
|
||||||
|
<p>${subtitle_start} - ${subtitle_end}</p>
|
||||||
|
<p>${subtitleLine}</p>
|
||||||
|
<div>
|
||||||
|
<a href="/channel/${channelId}/"><h3>${channelName}</h3></a>
|
||||||
|
<a class="video-more" href="/video/${videoId}/"><h2>${videoTitle}</h2></a>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
`
|
||||||
|
const fullTextDiv = document.createElement("div");
|
||||||
|
fullTextDiv.setAttribute("class", "video-item list");
|
||||||
|
fullTextDiv.innerHTML = markup;
|
||||||
|
return fullTextDiv
|
||||||
|
}
|
||||||
|
|
||||||
// generic
|
// generic
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue