make a YearNavigator availabel, useable as SearchEvent.naviator plugin.

It can take any Date field of the index and displays a list of year strings
in reverse order by the year (not the score/count).
To allow to define the index field to use, the fieldname (and title can be 
appended to the navi's name "year" e.g. year:load_date_dt:LoadDate
It works also with dates_in_content_dts field (from the graphical date
navigator). Here the query parameter from: to: are used on selection as
Query modifier (for other dates currently no query parameter available, so
selection won't work to filter search results).
Not included in the UI Searchpage layout config so far (for experiment with
it manual change to conf needed).
pull/93/head
reger 8 years ago
parent 7742579ca4
commit 08a0acc35d

@ -854,7 +854,7 @@ search.result.show.snapshots = false
# can be temporary different if search string is given with differen 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
#search.navigation=location,hosts,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

@ -444,14 +444,13 @@ public class yacysearchtrailer {
if (count == 0) {
break;
}
String encname = ((name.indexOf(' ', 0) < 0) ? name : "(" + name + ")");
rawNav = navi.getQueryModifier(name);
try {
nav = URLEncoder.encode(navi.getQueryModifier() + encname, StandardCharsets.UTF_8.name());
nav = URLEncoder.encode(rawNav, StandardCharsets.UTF_8.name());
} catch (UnsupportedEncodingException ex) {
nav = "";
}
rawNav = navi.getQueryModifier() + encname;
boolean isactive = navi.modifieractive(theSearch.query.modifier, name);
if (!isactive) {
pos++;

@ -212,8 +212,9 @@ public class ConcurrentScoreMap<E> extends AbstractScoreMap<E> implements ScoreM
}
/**
* @param up true = asc order, fals = reverse order
* @return iteratior accessing the keys in ordered by score values
* Creates and returns a sorted view to the keys. Sortorder is the score value.
* @param up true = asc order, false = reverse order
* @return iterator accessing the keys in order of score values
*/
@Override
public Iterator<E> keys(final boolean up) {
@ -222,7 +223,7 @@ public class ConcurrentScoreMap<E> extends AbstractScoreMap<E> implements ScoreM
Set<E> s;
Integer is;
for (final Map.Entry<E, AtomicInteger> entry: this.map.entrySet()) {
is = new Integer(entry.getValue().intValue());
is = entry.getValue().intValue();
s = m.get(is);
if (s == null) {
s = new HashSet<E>();

@ -79,8 +79,8 @@ public class LanguageNavigator extends StringNavigator implements Navigator {
}
@Override
public String getQueryModifier() {
return "/language/";
public String getQueryModifier(final String key) {
return "/language/" + key;
}
/**
@ -89,7 +89,7 @@ public class LanguageNavigator extends StringNavigator implements Navigator {
* @return display name of language
*/
@Override
public String getElementDisplayName(String lng) {
public String getElementDisplayName(final String lng) {
String longname = ISO639.country(lng);
if (longname == null) {
return lng;
@ -105,7 +105,7 @@ public class LanguageNavigator extends StringNavigator implements Navigator {
* @return true if contained in modifier.language
*/
@Override
public boolean modifieractive(QueryModifier modifier, String name) {
public boolean modifieractive(final QueryModifier modifier, final String name) {
if (modifier.language != null && modifier.language.contains(name)) {
return true;
} else {

@ -37,9 +37,9 @@ public class NameSpaceNavigator extends StringNavigator implements Navigator {
}
@Override
public String getQueryModifier() {
return "inurl:";
}
public String getQueryModifier(final String key) {
return "inurl:" + key;
}
@Override
public void incDocList(List<URIMetadataNode> docs) {

@ -47,15 +47,15 @@ public interface Navigator extends ScoreMap<String> {
* @param key original key as counted in this navigator
* @return a translated display text for a key
*/
public String getElementDisplayName(String key) ;
public String getElementDisplayName(final String key) ;
/**
* Returns the query modifier prefix. This is used (needed) within the servlet
* Returns the query modifier. This is used (needed) within the servlet
* to create a new modifier for a activated (clicked) navigator item.
*
* @return the query modifier prefix (if any, eg. "filetype:" or "author:" )
*/
public String getQueryModifier() ;
public String getQueryModifier(final String key) ;
/**
* Add counts for this navigator from documents in the provided list.
@ -92,7 +92,7 @@ public interface Navigator extends ScoreMap<String> {
* @param name the navigator key to check
* @return true if navigator key is mentioned as modifier
*/
public boolean modifieractive(QueryModifier modifier, String name);
public boolean modifieractive(final QueryModifier modifier, final String name);
/**
* @return the name of the index field, the fieldname counted in incDoc, incDoclList, incFacet

@ -22,6 +22,7 @@
*/
package net.yacy.search.navigator;
import java.util.Collection;
import java.util.List;
import java.util.Map;
import net.yacy.cora.sorting.ConcurrentScoreMap;
@ -51,35 +52,36 @@ public class StringNavigator extends ConcurrentScoreMap<String> implements Navi
}
@Override
public String getElementDisplayName(String e) {
public String getElementDisplayName(final String e) {
return e;
}
@Override
public String getQueryModifier() {
public String getQueryModifier(final String key) {
String mod;
if (field != null) {
switch (field) {
case author_sxt:
mod = "author:";
String tmpkey = key.indexOf(' ') > 0 ? "(" + key + ")" : key; // may contain spaces
mod = "author:" + tmpkey;
break;
case url_protocol_s:
mod = "/";
mod = "/" + key;
break;
case url_file_ext_s:
mod = "filetype:";
mod = "filetype:" + key;
break;
case collection_sxt:
mod = "collection:";
mod = "collection:" + key;
break;
case host_s:
mod = "site:";
mod = "site:" + key;
break;
case language_s:
mod = "/language/";
mod = "/language/" + key;
break;
default:
mod = ":";
mod = key;
}
} else {
mod = "";
@ -106,19 +108,24 @@ public class StringNavigator extends ConcurrentScoreMap<String> implements Navi
}
}
/**
* Increase the score for the key value contained in the defined field in
* the doc.
* @param doc Solrdocument with field for the key content
*/
@Override
public void incDoc(URIMetadataNode doc) {
if (field != null) {
Object val = doc.getFieldValue(field.getSolrFieldName());
if (val instanceof List) {
List<String> ll = (List) val;
for (String s : ll) {
if (!s.isEmpty()) {
this.inc(s);
if (val != null) {
if (val instanceof Collection) {
Collection<String> ll = (Collection) val;
for (String s : ll) {
if (!s.isEmpty()) {
this.inc(s);
}
}
}
} else {
if (val != null) {
} else {
this.inc((String) val);
}
}
@ -126,12 +133,8 @@ public class StringNavigator extends ConcurrentScoreMap<String> implements Navi
}
@Override
public boolean modifieractive(QueryModifier modifier, String name) {
if (name.indexOf(' ') < 0) {
return modifier.toString().contains(getQueryModifier() + name);
} else {
return modifier.toString().contains(getQueryModifier() + "(" + name + ")");
}
public boolean modifieractive(final QueryModifier modifier, final String name) {
return modifier.toString().contains(getQueryModifier(name));
}
@Override

@ -0,0 +1,161 @@
/**
* YearNavigator.java
* (C) 2016 by reger24; https://github.com/reger24
*
* This is a part of YaCy, a peer-to-peer based web search engine
*
* LICENSE
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program.
* If not, see <http://www.gnu.org/licenses/>.
*/
package net.yacy.search.navigator;
import java.util.Collection;
import java.util.Collections;
import java.util.Date;
import java.util.Iterator;
import java.util.Map;
import java.util.TreeSet;
import net.yacy.cora.federate.solr.SolrType;
import net.yacy.cora.sorting.ReversibleScoreMap;
import net.yacy.kelondro.data.meta.URIMetadataNode;
import net.yacy.search.query.QueryModifier;
import net.yacy.search.schema.CollectionSchema;
/**
* Navigator for date fields, showing the year of the date, ordered by the key =
* year string
*
* following fields are declared as SorlType.date (and can be used by YearNavigator)
* last_modified  
* dates_in_content_dts       
* startDates_dts     
* endDates_dts
* load_date_dt       
* fresh_date_dt
*
* as of now the config (in yacy.init/yacy.conf can be used to define the field
* to use by adding : (colon) fieldname, optional :Titlestring
* example: search.navigation=year:last_modified:Year
*
*/
public class YearNavigator extends StringNavigator implements Navigator {
public YearNavigator(String title, CollectionSchema field) {
super(title, field);
if (field.getType() != SolrType.date) throw new IllegalArgumentException("field is not of type Date");
}
/**
* For dates_in_content_dts a special modifier is returned to limit date for
* the full year using from:YEAR-01-01 to:YEAR-12-31
* @param key
* @return from:key-01-01 to:key-12-31
*/
@Override
public String getQueryModifier(final String key) {
if (this.field == CollectionSchema.dates_in_content_dts)
return "from:" + key +"-01-01 to:" + key + "-12-31 ";
else
return key;
}
/**
* Shortens the facet date field to a year and increases count
* @param facets
*/
@Override
public void incFacet(Map<String, ReversibleScoreMap<String>> facets) {
if (field != null && facets != null && !facets.isEmpty()) {
ReversibleScoreMap<String> fcts = facets.get(field.getSolrFieldName());
if (fcts != null) {
Iterator<String> it = fcts.iterator();
// loop through the facet to extract the year
while (it.hasNext()) {
String datestring = it.next();
this.inc(datestring.substring(0, 4), fcts.get(datestring));
}
}
}
}
@Override
public void incDoc(URIMetadataNode doc) {
if (field != null) {
if (field.getType() == SolrType.date) {
Object val = doc.getFieldValue(field.getSolrFieldName());
if (val != null) {
if (val instanceof Collection) {
Collection<Object> ll = (Collection) val;
for (Object o : ll) {
if (o instanceof String) {
this.inc((String) o);
} else if (o instanceof Date) {
Date dd = (Date) o;
String year = Integer.toString(dd.getYear() + 1900);
this.inc(year);
}
}
} else {
Date dd = (Date) val;
String year = Integer.toString(dd.getYear() + 1900);
this.inc(year);
}
}
}
}
}
/**
* YearNavigator returns keys in asc or desc order instead of ordered by
* score
*
* @param up true = asc
* @return key alphabetically ordered
*/
@Override
public Iterator<String> keys(boolean up) {
TreeSet<String> years;
if (up) {
years = new TreeSet<String>();
} else {
years = new TreeSet(Collections.reverseOrder());
}
Iterator<String> it = this.iterator();
while (it.hasNext()) {
years.add(it.next());
}
return years.iterator();
}
/**
* For date_in_content_dts it return true if form:YEAR and to:YEAR is part
* of the modifier, otherwise false.
* @param modifier
* @param name 4 digit year string
* @return
*/
@Override
public boolean modifieractive(QueryModifier modifier, String name) {
if (this.field == CollectionSchema.dates_in_content_dts) {
if (modifier.toString().contains("from:" + name) && modifier.toString().contains("to:" + name)) {
return true;
}
}
return false;
}
}

@ -102,6 +102,7 @@ import net.yacy.search.navigator.NameSpaceNavigator;
import net.yacy.search.navigator.Navigator;
import net.yacy.search.navigator.RestrictedStringNavigator;
import net.yacy.search.navigator.StringNavigator;
import net.yacy.search.navigator.YearNavigator;
import net.yacy.search.ranking.ReferenceOrder;
import net.yacy.search.schema.CollectionConfiguration;
import net.yacy.search.schema.CollectionSchema;
@ -294,6 +295,25 @@ public final class SearchEvent {
if (navname.contains("namespace")) {
this.navigatorPlugins.put("namespace", new NameSpaceNavigator("Name Space"));
}
// YearNavigator with possible def of :fieldname:title in configstring
if (navname.contains("year")) {
if ((navname.indexOf(':')) > 0) { // example "year:dates_in_content_dts:Events"
String[] navfielddef = navname.split(":");
try {
// year:fieldname:title
CollectionSchema field = CollectionSchema.valueOf(navfielddef[1]);
if (navfielddef.length > 2) {
this.navigatorPlugins.put(navfielddef[1], new YearNavigator(navfielddef[2], field));
} else {
this.navigatorPlugins.put(navfielddef[1], new YearNavigator("Year-" + navfielddef[1], field));
}
} catch (java.lang.IllegalArgumentException ex) {
log.severe("wrong navigator name in config: \"" + navname + "\" " + ex.getMessage());
}
} else { // "year" only use default last_modified
this.navigatorPlugins.put("year", new YearNavigator("Year", CollectionSchema.last_modified));
}
}
}
this.snippets = new ConcurrentHashMap<String, LinkedHashSet<String>>();

Loading…
Cancel
Save