Skip to content
Permalink
Browse files

Added the possibility to customize facets sort type and direction

Previously search navigators/facets elements were sorted only by counts.
Now from the ConfigSearchPage_p.html admin page, sort direction
(ascending/descending) and type (on counts or labels) can be customized
independently for each navigator.
  • Loading branch information...
luccioman committed Jan 24, 2019
1 parent d3a114c commit 9782a98a9c1b60e00423ae1cae380647f2f198d4
@@ -932,10 +932,12 @@ search.result.show.ranking = false


# search navigators: comma-separated list of default values for search navigation.
# can be temporary different if search string is given with differen navigation values
# By default navigators keys are sorted by descending counts. To sort by ascending displayed labels, add the :label suffix (example : hosts:label).
# The sort direction can also be specified with the :asc or :desc suffixes (example : hosts:label:desc)
# can be temporary different if search string is given with different navigation values
# assigning no value(s) means that no navigation is shown
search.navigation=location,hosts,authors,namespace,topics,filetype,protocol,language
#search.navigation=location,hosts,authors,namespace,topics,filetype,protocol,language,collections,date,year,year:dates_in_content_dts:Event
#search.navigation=location,hosts:label,authors,namespace,topics,filetype,protocol,language,collections,date,year,year:dates_in_content_dts:Event

# max number of items displayed in search navigators
search.navigation.maxcount=100
@@ -139,16 +139,36 @@ <h4>Page Template</h4>
#{search.navigation.plugin}#
<tr>
<td><button class="btn btn-xs" title="Delete navigator" aria-label="Delete navigator" aria-describedby="title-#[name]#" name="del.nav" value="#[name]#"><span class="glyphicon glyphicon-remove" style="color: red"></span></button></td>
<td><ul class="nav nav-sidebar menugroup" style="padding-left:15px; padding-right:10px;">
<li><h3 id="title-#[name]#">#[displayname]#</h3></li>
</ul><input type="hidden" name="search.navigation.active" value="#[name]#" />
<td>
<ul class="nav nav-sidebar menugroup" style="padding-left:15px; padding-right:10px;">
<li>
<h3 id="title-#[name]#">#[displayname]#
#(navSort)#<span class="glyphicon glyphicon-sort-by-attributes-alt" title="Sorted by descending counts"></span>
::<span class="glyphicon glyphicon-sort-by-attributes" title="Sorted by ascending counts"></span>
::<span class="glyphicon glyphicon glyphicon-sort-by-alphabet-alt" title="Sorted by descending labels"></span>
::<span class="glyphicon glyphicon-sort-by-alphabet" title="Sorted by ascending labels"></span>
#(/navSort)#
</h3>
</li>
<li>
<label>Sort by
<select name="search.navigation.#[name]#.navSort">
<option value="count:desc" #(navSort)#selected="selected"::#(/navSort)#>Descending counts</option>
<option value="count:asc" #(navSort)#::selected="selected"#(/navSort)#>Ascending counts</option>
<option value="label:desc" #(navSort)#::::selected="selected"#(/navSort)#>Descending labels</option>
<option value="label:asc" #(navSort)#::::::selected="selected"#(/navSort)#>Ascending labels</option>
</select>
</label>
</li>
</ul>
<input type="hidden" name="search.navigation.active" value="#[name]#" />
</td>
</tr>
#{/search.navigation.plugin}#
<tr>
<td></td>
<td><ul class="nav nav-sidebar menugroup" id="vocabulary" style="padding-left:15px; padding-right:10px;">
<li><h3>Vocabulary</h3></li>
<li><h3>Vocabulary <span class="glyphicon glyphicon-sort-by-attributes-alt" title="Sorted by descending counts"></span></h3></li>
</ul></td>
</tr>
<tr>
@@ -30,8 +30,10 @@
import java.io.FileNotFoundException;
import java.io.IOException;
import java.sql.Date;
import java.util.HashSet;
import java.util.Map;
import java.util.Properties;
import java.util.Set;

import net.yacy.cora.date.GenericFormatter;
import net.yacy.cora.protocol.RequestHeader;
@@ -42,7 +44,11 @@
import net.yacy.search.SwitchboardConstants;
import net.yacy.search.navigator.Navigator;
import net.yacy.search.navigator.NavigatorPlugins;
import net.yacy.search.navigator.NavigatorSort;
import net.yacy.search.navigator.NavigatorSortDirection;
import net.yacy.search.navigator.NavigatorSortType;
import net.yacy.search.query.QueryParams;
import net.yacy.search.query.SearchEventCache;
import net.yacy.server.serverObjects;
import net.yacy.server.serverSwitch;

@@ -56,6 +62,10 @@ public static serverObjects respond(final RequestHeader header, final serverObje
/* Check this is a valid transaction */
TransactionManager.checkPostTransaction(header, post);

final int initialNavMaxCOunt = sb.getConfigInt(
SwitchboardConstants.SEARCH_NAVIGATION_MAXCOUNT, QueryParams.FACETS_STANDARD_MAXCOUNT_DEFAULT);
final String initialNavConf = sb.getConfig("search.navigation", "");

if (post.containsKey("searchpage_set")) {
final String newGreeting = post.get(SwitchboardConstants.GREETING, "");
// store this call as api call
@@ -96,24 +106,33 @@ public static serverObjects respond(final RequestHeader header, final serverObje
sb.setConfig("search.result.show.snapshots", post.getBoolean("search.result.show.snapshots"));

// construct navigation String
String nav = "";
if (post.getBoolean("search.navigation.location")) nav += "location,";
// if (post.getBoolean("search.navigation.filetype")) nav += "filetype,";
if (post.getBoolean("search.navigation.protocol")) nav += "protocol,";
// if (post.getBoolean("search.navigation.hosts")) nav += "hosts,";
// if (post.getBoolean("search.navigation.language")) nav += "language,";
// if (post.getBoolean("search.navigation.authors")) nav += "authors,";
// if (post.getBoolean("search.navigation.collections")) nav += "collections,";
// if (post.getBoolean("search.navigation.namespace")) nav += "namespace,";
if (post.getBoolean("search.navigation.topics")) nav += "topics,";
if (post.getBoolean("search.navigation.date")) nav += "date,";
Set<String> navConfigs = new HashSet<>();
if (post.getBoolean("search.navigation.location")) {
navConfigs.add("location");
}
if (post.getBoolean("search.navigation.protocol")) {
navConfigs.add("protocol");
}
if (post.getBoolean("search.navigation.topics")) {
navConfigs.add("topics");
}
if (post.getBoolean("search.navigation.date")) {
navConfigs.add("date");
}
// append active navigator plugins
String[] navplugins = post.getAll("search.navigation.active");
for (String navname:navplugins) {
nav += navname + ",";
String[] activeNavNames = post.getAll("search.navigation.active");
for (final String navName : activeNavNames) {
String navConfig = navName;
final String navSortConfig = post.get("search.navigation." + navName + ".navSort");
final NavigatorSort defaultSort = NavigatorPlugins.getDefaultSort(navName);
if (NavigatorPlugins.parseNavSortConfig(
navName + NavigatorPlugins.NAV_PROPS_CONFIG_SEPARATOR + navSortConfig,
defaultSort) != defaultSort) {
navConfig += NavigatorPlugins.NAV_PROPS_CONFIG_SEPARATOR + navSortConfig;
}
navConfigs.add(navConfig);
}
if (nav.endsWith(",")) nav = nav.substring(0, nav.length() - 1);
sb.setConfig("search.navigation", nav);
sb.setConfig("search.navigation", navConfigs);
// maxcount nav entries, default
int navmaxcnt = post.getInt(SwitchboardConstants.SEARCH_NAVIGATION_MAXCOUNT, QueryParams.FACETS_STANDARD_MAXCOUNT_DEFAULT);
if (navmaxcnt > 5) {
@@ -131,16 +150,15 @@ public static serverObjects respond(final RequestHeader header, final serverObje
if (post.containsKey("add.nav")) { // button: add navigator plugin to ative list
String navname = post.get("search.navigation.navname");
if (navname != null && !navname.isEmpty()) {
String naviconf = sb.getConfig("search.navigation", "");
naviconf += "," + navname;
sb.setConfig("search.navigation", naviconf);
final Set<String> navConfigs = sb.getConfigSet("search.navigation");
navConfigs.add(navname);
sb.setConfig("search.navigation", navConfigs);
}
} else if (post.containsKey("del.nav")) { // button: delete navigator plugin from active list
String navname = post.get("del.nav");
String naviconf = sb.getConfig("search.navigation", "");
naviconf = naviconf.replace(navname, "");
naviconf = naviconf.replace(",,", ",");
sb.setConfig("search.navigation", naviconf);
final String navToDelete = post.get("del.nav");
final Set<String> navConfigs = sb.getConfigSet("search.navigation");
navConfigs.removeIf(navConfig -> NavigatorPlugins.getNavName(navConfig).equals(navToDelete));
sb.setConfig("search.navigation", navConfigs);
}

if (post.containsKey("searchpage_default")) {
@@ -203,6 +221,12 @@ public static serverObjects respond(final RequestHeader header, final serverObje
config.getProperty(SwitchboardConstants.SEARCH_NAVIGATION_DATES_MAXCOUNT,
String.valueOf(QueryParams.FACETS_DATE_MAXCOUNT_DEFAULT)));
}

if(!initialNavConf.equals(sb.getConfig("search.navigation", "")) || initialNavMaxCOunt != sb.getConfigInt(
SwitchboardConstants.SEARCH_NAVIGATION_MAXCOUNT, QueryParams.FACETS_STANDARD_MAXCOUNT_DEFAULT)) {
/* Clean up search events cache when necessary */
SearchEventCache.cleanupEvents(true);
}
}

/* Acquire a transaction token for the next POST form submission */
@@ -252,24 +276,54 @@ public static serverObjects respond(final RequestHeader header, final serverObje
prop.put("search.result.show.snapshots", sb.getConfigBool("search.result.show.snapshots", false) ? 1 : 0);
prop.put("search.result.show.ranking", sb.getConfigBool(SwitchboardConstants.SEARCH_RESULT_SHOW_RANKING, SwitchboardConstants.SEARCH_RESULT_SHOW_RANKING_DEFAULT) ? 1 : 0);

prop.put("search.navigation.location", sb.getConfig("search.navigation", "").indexOf("location",0) >= 0 ? 1 : 0);
// prop.put("search.navigation.filetype", sb.getConfig("search.navigation", "").indexOf("filetype",0) >= 0 ? 1 : 0);
prop.put("search.navigation.protocol", sb.getConfig("search.navigation", "").indexOf("protocol",0) >= 0 ? 1 : 0);
// prop.put("search.navigation.hosts", sb.getConfig("search.navigation", "").indexOf("hosts",0) >= 0 ? 1 : 0);
// prop.put("search.navigation.language", sb.getConfig("search.navigation", "").indexOf("language",0) >= 0 ? 1 : 0);
// prop.put("search.navigation.authors", sb.getConfig("search.navigation", "").indexOf("authors",0) >= 0 ? 1 : 0);
// prop.put("search.navigation.collections", sb.getConfig("search.navigation", "").indexOf("collections",0) >= 0 ? 1 : 0);
// prop.put("search.navigation.namespace", sb.getConfig("search.navigation", "").indexOf("namespace",0) >= 0 ? 1 : 0);
prop.put("search.navigation.topics", sb.getConfig("search.navigation", "").indexOf("topics",0) >= 0 ? 1 : 0);
prop.put("search.navigation.date", sb.getConfig("search.navigation", "").indexOf("date",0) >= 0 ? 1 : 0);
final Set<String> navConfigs = sb.getConfigSet("search.navigation");
boolean locationNavEnabled = false;
boolean protocolNavEnabled = false;
boolean topicsNavEnabled = false;
boolean dateNavEnabled = false;
for(final String navConfig : navConfigs) {
final String navName = NavigatorPlugins.getNavName(navConfig);
if("location".equals(navName)) {
locationNavEnabled = true;
} else if("protocol".equals(navName)) {
protocolNavEnabled = true;
} else if("topics".equals(navName)) {
topicsNavEnabled = true;
} else if("date".equals(navName)) {
dateNavEnabled = true;
}
}

prop.put("search.navigation.location", locationNavEnabled);
prop.put("search.navigation.protocol", protocolNavEnabled);
prop.put("search.navigation.topics", topicsNavEnabled);
prop.put("search.navigation.date", dateNavEnabled);
// list active navigator plugins
String naviconf = sb.getConfig("search.navigation", "");
Map<String, Navigator> navplugins = NavigatorPlugins.initFromCfgString(naviconf);
Map<String, Navigator> navplugins = NavigatorPlugins.initFromCfgStrings(navConfigs);
int i = 0;
for (String navname:navplugins.keySet()) {
for (final String navname : navplugins.keySet()) {
Navigator nav = navplugins.get(navname);
prop.put("search.navigation.plugin_" + i + "_name", navname);
prop.put("search.navigation.plugin_" + i + "_displayname", nav.getDisplayName());
final int navSort;
if(nav.getSort() == null) {
navSort = 0;
} else {
if(nav.getSort().getSortType() == NavigatorSortType.COUNT) {
if(nav.getSort().getSortDir() == NavigatorSortDirection.DESC) {
navSort = 0;
} else {
navSort = 1;
}
} else {
if(nav.getSort().getSortDir() == NavigatorSortDirection.DESC) {
navSort = 2;
} else {
navSort = 3;
}
}
}
prop.put("search.navigation.plugin_" + i + "_navSort", navSort);
i++;
}
prop.put("search.navigation.plugin", i);
@@ -30,6 +30,7 @@
import java.util.Arrays;
import java.util.Collection;
import java.util.Date;
import java.util.HashSet;
import java.util.Iterator;
import java.util.List;
import java.util.regex.PatternSyntaxException;
@@ -63,8 +64,8 @@
import net.yacy.peers.Protocol;
import net.yacy.peers.Seed;
import net.yacy.repository.Blacklist;
import net.yacy.repository.BlacklistHostAndPath;
import net.yacy.repository.Blacklist.BlacklistType;
import net.yacy.repository.BlacklistHostAndPath;
import net.yacy.search.Switchboard;
import net.yacy.search.SwitchboardConstants;
import net.yacy.search.index.Segment;
@@ -680,7 +681,7 @@ public static SearchEvent genSearchresult(
sb.getRanking(),
"",//userAgent
0.0d, 0.0d, 0.0d,
new String[0]);
new HashSet<>());
final SearchEvent theSearch = SearchEventCache.getEvent(query, sb.peers, sb.tables, null, false, sb.loader, Integer.MAX_VALUE, Long.MAX_VALUE);
if (theSearch.rwiProcess != null && theSearch.rwiProcess.isAlive()) try {theSearch.rwiProcess.join();} catch (final InterruptedException e) {}
if (theSearch.local_rwi_available.get() == 0) {
@@ -254,7 +254,7 @@ public static serverObjects respond(final RequestHeader header, final serverObje
0.0d,
0.0d,
0.0d,
new String[0]
new HashSet<>()
);
theQuery.setStrictContentDom(strictContentDom);
Network.log.info("INIT HASH SEARCH (abstracts only): " + QueryParams.anonymizedQueryHashes(theQuery.getQueryGoal().getIncludeHashes()) + " - " + theQuery.itemsPerPage() + " links");
@@ -319,7 +319,7 @@ public static serverObjects respond(final RequestHeader header, final serverObje
0.0d,
0.0d,
0.0d,
new String[0]
new HashSet<>()
);
theQuery.setStrictContentDom(strictContentDom);
Network.log.info("INIT HASH SEARCH (query-" + abstracts + "): " + QueryParams.anonymizedQueryHashes(theQuery.getQueryGoal().getIncludeHashes()) + " - " + theQuery.itemsPerPage() + " links");
@@ -700,7 +700,7 @@ public static serverObjects respond(
ranking,
header.get(HeaderFramework.USER_AGENT, ""),
lat, lon, rad,
sb.getConfigArray("search.navigation", ""));
sb.getConfigSet("search.navigation"));
theQuery.setStrictContentDom(strictContentDom);
theQuery.setMaxSuggestions(meanMax);
theQuery.setStandardFacetsMaxCount(sb.getConfigInt(SwitchboardConstants.SEARCH_NAVIGATION_MAXCOUNT,
@@ -189,7 +189,15 @@
#{navs}#
<ul id="nav-#[name]#" class="nav nav-sidebar menugroup">
<li style="cursor: pointer; cursor: hand;"><h3 onclick="toggleVisibility('#[name]#', #[count]#);">#[displayname]# [#[count]#] <span style="float:right" id="chevron-#[name]#" class="glyphicon glyphicon-chevron-down" title="click to expand facet"></span></h3></li>
<li style="cursor: pointer; cursor: hand;">
<h3 onclick="toggleVisibility('#[name]#', #[count]#);">#[displayname]# [#[count]#]
#(navSort)#<span class="glyphicon glyphicon-sort-by-attributes-alt" title="Sorted by descending counts"></span>
::<span class="glyphicon glyphicon-sort-by-attributes" title="Sorted by ascending counts"></span>
::<span class="glyphicon glyphicon glyphicon-sort-by-alphabet-alt" title="Sorted by descending labels"></span>
::<span class="glyphicon glyphicon-sort-by-alphabet" title="Sorted by ascending labels"></span>#(/navSort)#
<span style="float:right" id="chevron-#[name]#" class="glyphicon glyphicon-chevron-down" title="click to expand facet"></span>
</h3>
</li>
#{element}#
<li style="display:none" id="#[id]#"><a href="#[url]#" class="MenuItemLink"><input type="checkbox" onchange="window.location.href='#[url]#'"#(on)# checked="checked"::#(/on)#/> #[name]# (#[count]#)</a></li>
#{/element}#</ul>
@@ -198,7 +206,12 @@
#{nav-vocabulary}#
<ul id="nav-vocabulary" class="nav nav-sidebar menugroup">
<li style="cursor: pointer; cursor: hand;"><h3 onclick="toggleVisibility('vocabulary_#[navname]#', #[count]#);">#[navname]# [#[count]#] <span style="float:right" id="chevron-vocabulary_#[navname]#" class="glyphicon glyphicon-chevron-down" title="click to expand facet"></span></h3></li>
<li style="cursor: pointer; cursor: hand;">
<h3 onclick="toggleVisibility('vocabulary_#[navname]#', #[count]#);">#[navname]# [#[count]#]
<span class="glyphicon glyphicon-sort-by-attributes-alt" title="Sorted by descending counts"></span>
<span style="float:right" id="chevron-vocabulary_#[navname]#" class="glyphicon glyphicon-chevron-down" title="click to expand facet"></span>
</h3>
</li>
#{element}#
<li style="display:none" id="#[id]#"><a href="#[url]#" class="MenuItemLink"><input type="checkbox" onchange="window.location.href='#[url]#'"#(on)# checked="checked"::#(/on)#/> #[name]# (#[count]#)</a></li>
#{/element}#</ul>

0 comments on commit 9782a98

Please sign in to comment.
You can’t perform that action at this time.