%PDF- %PDF-
| Direktori : /home/waritko/yacy/source/net/yacy/cora/federate/solr/responsewriter/ |
| Current File : //home/waritko/yacy/source/net/yacy/cora/federate/solr/responsewriter/YJsonResponseWriter.java |
/**
* JsonResponseWriter
* Copyright 2012 by Michael Peter Christen
* First released 10.09.2012 at http://yacy.net
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This library 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
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this program in the file lgpl21.txt
* If not, see <http://www.gnu.org/licenses/>.
*/
package net.yacy.cora.federate.solr.responsewriter;
import java.io.IOException;
import java.io.Writer;
import java.net.MalformedURLException;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Date;
import java.util.HashMap;
import java.util.LinkedHashSet;
import java.util.List;
import java.util.Locale;
import java.util.Map;
import java.util.Map.Entry;
import org.apache.lucene.document.Document;
import org.apache.lucene.index.IndexableField;
import org.apache.solr.client.solrj.response.QueryResponse;
import org.apache.solr.common.SolrDocument;
import org.apache.solr.common.SolrDocumentList;
import org.apache.solr.common.util.NamedList;
import org.apache.solr.common.util.SimpleOrderedMap;
import org.apache.solr.request.SolrQueryRequest;
import org.apache.solr.response.QueryResponseWriter;
import org.apache.solr.response.ResultContext;
import org.apache.solr.response.SolrQueryResponse;
import org.apache.solr.search.DocIterator;
import org.apache.solr.search.DocList;
import org.apache.solr.search.SolrIndexSearcher;
import org.json.JSONObject;
import net.yacy.cora.document.id.MultiProtocolURL;
import net.yacy.cora.federate.solr.responsewriter.OpensearchResponseWriter.ResHead;
import net.yacy.cora.protocol.HeaderFramework;
import net.yacy.cora.util.ConcurrentLog;
import net.yacy.crawler.retrieval.Response;
import net.yacy.search.schema.CollectionConfiguration;
import net.yacy.search.schema.CollectionSchema;
/**
* write the opensearch result in YaCys special way to include as much as in opensearch is included.
* This will also include YaCy facets.
*
* example:
* http://localhost:8090/solr/select?hl=false&wt=yjson&facet=true&facet.mincount=1&facet.field=host_s&facet.field=url_file_ext_s&facet.field=url_protocol_s&facet.field=author_sxt&facet.field=collection_sxt&start=0&rows=10&query=www
*/
public class YJsonResponseWriter implements QueryResponseWriter, SolrjResponseWriter {
// define a list of simple YaCySchema -> json Token matchings
private static final Map<String, String> field2tag = new HashMap<>();
static {
field2tag.put(CollectionSchema.url_protocol_s.getSolrFieldName(), "protocol");
field2tag.put(CollectionSchema.host_s.getSolrFieldName(), "host");
field2tag.put(CollectionSchema.url_file_ext_s.getSolrFieldName(), "ext");
}
private String title;
public YJsonResponseWriter() {
super();
}
public void setTitle(String searchPageTitle) {
this.title = searchPageTitle;
}
@Override
public String getContentType(final SolrQueryRequest request, final SolrQueryResponse response) {
return "application/json; charset=UTF-8";
}
@Override
public void init(@SuppressWarnings("rawtypes") NamedList n) {
}
@Override
public void write(final Writer writer, final SolrQueryRequest request, final SolrQueryResponse rsp) throws IOException {
final NamedList<?> values = rsp.getValues();
final Object responseObj = rsp.getResponse();
write(writer, request, values, responseObj);
}
@Override
public void write(Writer writer, SolrQueryRequest request, String coreName, QueryResponse rsp) throws IOException {
final NamedList<Object> values = rsp.getResponse();
final SolrDocumentList documents = rsp.getResults();
write(writer, request, values, documents);
}
/**
* Append to the writer the YaCy json representation of the Solr results.
* @param writer an open output writer. Must not be null.
* @param request the initial Solr request. Must not be null.
* @param values the response values. Must not be null.
* @param rsp the Solr response header.
* @throws IOException when a write error occurred
*/
private void write(final Writer writer, final SolrQueryRequest request, final NamedList<?> values,
final Object responseObj) throws IOException {
assert values.get("response") != null;
@SuppressWarnings("unchecked")
SimpleOrderedMap<Object> facetCounts = (SimpleOrderedMap<Object>) values.get("facet_counts");
@SuppressWarnings("unchecked")
SimpleOrderedMap<Object> facetFields = facetCounts == null || facetCounts.size() == 0 ? null : (SimpleOrderedMap<Object>) facetCounts.get("facet_fields");
final Object highlightingObj = values.get("highlighting");
final Map<String, Collection<String>> snippets = highlightingObj instanceof NamedList
? OpensearchResponseWriter.snippetsFromHighlighting((NamedList<?>) highlightingObj)
: new HashMap<>();
// parse response header
final ResHead resHead = new ResHead();
resHead.rows = request.getOriginalParams().getLong("rows", -1);
String jsonp = request.getParams().get("callback"); // check for JSONP
if (jsonp != null) {
writer.write(jsonp.toCharArray());
writer.write("([".toCharArray());
}
if(responseObj instanceof ResultContext){
/* Regular response object */
final DocList documents = ((ResultContext)responseObj).getDocList();
resHead.offset = documents.offset(); // equal to 'start' Solr param
resHead.numFound = documents.matches();
writeHeader(writer, resHead);
writeDocs(writer, documents, request, snippets);
} else if(responseObj instanceof SolrDocumentList) {
/*
* The response object can be a SolrDocumentList when the response is partial,
* for example when the allowed processing time has been exceeded
*/
final SolrDocumentList documents = ((SolrDocumentList)responseObj);
resHead.offset = documents.getStart(); // equal to 'start' Solr param
resHead.numFound = documents.getNumFound();
writeHeader(writer, resHead);
writeDocs(writer, documents, snippets);
} else {
throw new IOException("Unable to process Solr response format");
}
writer.write("],\n".toCharArray());
writer.write("\"navigation\":[\n");
// the facets can be created with the options &facet=true&facet.mincount=1&facet.field=host_s&facet.field=url_file_ext_s&facet.field=url_protocol_s&facet.field=author_sxt
@SuppressWarnings("unchecked")
NamedList<Integer> domains = facetFields == null ? null : (NamedList<Integer>) facetFields.get(CollectionSchema.host_s.getSolrFieldName());
@SuppressWarnings("unchecked")
NamedList<Integer> filetypes = facetFields == null ? null : (NamedList<Integer>) facetFields.get(CollectionSchema.url_file_ext_s.getSolrFieldName());
@SuppressWarnings("unchecked")
NamedList<Integer> protocols = facetFields == null ? null : (NamedList<Integer>) facetFields.get(CollectionSchema.url_protocol_s.getSolrFieldName());
@SuppressWarnings("unchecked")
NamedList<Integer> authors = facetFields == null ? null : (NamedList<Integer>) facetFields.get(CollectionSchema.author_sxt.getSolrFieldName());
@SuppressWarnings("unchecked")
NamedList<Integer> collections = facetFields == null ? null : (NamedList<Integer>) facetFields.get(CollectionSchema.collection_sxt.getSolrFieldName());
int facetcount = 0;
if (domains != null) {
writer.write(facetcount > 0 ? ",\n" : "\n");
writer.write("{\"facetname\":\"domains\",\"displayname\":\"Provider\",\"type\":\"String\",\"min\":\"0\",\"max\":\"0\",\"mean\":\"0\",\"elements\":[\n".toCharArray());
for (int i = 0; i < domains.size(); i++) {
facetEntry(writer, "site", domains.getName(i), Integer.toString(domains.getVal(i)));
if (i < domains.size() - 1) writer.write(',');
writer.write("\n");
}
writer.write("]}".toCharArray());
facetcount++;
}
if (filetypes != null) {
writer.write(facetcount > 0 ? ",\n" : "\n");
writer.write("{\"facetname\":\"filetypes\",\"displayname\":\"Filetypes\",\"type\":\"String\",\"min\":\"0\",\"max\":\"0\",\"mean\":\"0\",\"elements\":[\n".toCharArray());
List<Map.Entry<String, Integer>> l = new ArrayList<>();
for (Map.Entry<String, Integer> e: filetypes) {
if (e.getKey().length() <= 6) l.add(e);
if (l.size() >= 16) break;
}
for (int i = 0; i < l.size(); i++) {
Map.Entry<String, Integer> e = l.get(i);
facetEntry(writer, "filetype", e.getKey(), Integer.toString(e.getValue()));
if (i < l.size() - 1) writer.write(',');
writer.write("\n");
}
writer.write("]}".toCharArray());
facetcount++;
}
if (protocols != null) {
writer.write(facetcount > 0 ? ",\n" : "\n");
writer.write("{\"facetname\":\"protocols\",\"displayname\":\"Protocol\",\"type\":\"String\",\"min\":\"0\",\"max\":\"0\",\"mean\":\"0\",\"elements\":[\n".toCharArray());
for (int i = 0; i < protocols.size(); i++) {
facetEntry(writer, "protocol", protocols.getName(i), Integer.toString(protocols.getVal(i)));
if (i < protocols.size() - 1) writer.write(',');
writer.write("\n");
}
writer.write("]}".toCharArray());
facetcount++;
}
if (authors != null) {
writer.write(facetcount > 0 ? ",\n" : "\n");
writer.write("{\"facetname\":\"authors\",\"displayname\":\"Authors\",\"type\":\"String\",\"min\":\"0\",\"max\":\"0\",\"mean\":\"0\",\"elements\":[\n".toCharArray());
for (int i = 0; i < authors.size(); i++) {
facetEntry(writer, "author", authors.getName(i), Integer.toString(authors.getVal(i)));
if (i < authors.size() - 1) writer.write(',');
writer.write("\n");
}
writer.write("]}".toCharArray());
facetcount++;
}
if (collections != null) {
writer.write(facetcount > 0 ? ",\n" : "\n");
writer.write("{\"facetname\":\"collections\",\"displayname\":\"Collections\",\"type\":\"String\",\"min\":\"0\",\"max\":\"0\",\"mean\":\"0\",\"elements\":[\n".toCharArray());
for (int i = 0; i < collections.size(); i++) {
facetEntry(writer, "collection", collections.getName(i), Integer.toString(collections.getVal(i)));
if (i < collections.size() - 1) writer.write(',');
writer.write("\n");
}
writer.write("]}".toCharArray());
facetcount++;
}
writer.write("\n]}]}\n".toCharArray());
if (jsonp != null) {
writer.write("])".toCharArray());
}
}
/**
* Append to the writer the header of the YaCy json representation.
* @param writer an open output writer. Must not be null.
* @param resHead the calculated results head. Must not be null.
* @throws IOException when an unexpected error occurred while writing
*/
private void writeHeader(final Writer writer, final ResHead resHead)
throws IOException {
writer.write(("{\"channels\": [{\n").toCharArray());
solitaireTag(writer, "totalResults", Long.toString(resHead.numFound));
solitaireTag(writer, "startIndex", Long.toString(resHead.offset));
solitaireTag(writer, "itemsPerPage", Long.toString(resHead.rows));
solitaireTag(writer, "title", this.title);
solitaireTag(writer, "description", "Search Result");
writer.write("\"items\": [\n".toCharArray());
}
/**
* Append to the writer the OpenSearch RSS representation of Solr documents.
*
* @param writer an open output writer. Must not be null.
* @param documents the documents to render. Must not be null.
* @param snippets Solr computed text snippets (highlighting).
* @throws IOException when an unexpected error occurred while writing
*/
private void writeDocs(final Writer writer, final DocList documents, final SolrQueryRequest request,
final Map<String, Collection<String>> snippets) throws IOException {
final SolrIndexSearcher searcher = request.getSearcher();
final DocIterator iterator = documents.iterator();
int writtenDocs = 0;
while(iterator.hasNext()) {
if(writtenDocs > 0) {
writer.write(",\n".toCharArray());
}
try {
writer.write("{\n".toCharArray());
int id = iterator.nextDoc();
Document doc = searcher.doc(id, OpensearchResponseWriter.SOLR_FIELDS);
MultiProtocolURL url = null;
String urlhash = null;
List<String> descriptions = new ArrayList<>();
String docTitle = "";
StringBuilder path = new StringBuilder(80);
List<Object> imagesProtocolObjs = new ArrayList<>();
List<String> imagesStubs = new ArrayList<>();
for (final IndexableField value : doc.getFields()) {
String fieldName = value.name();
// apply generic matching rule
String stag = field2tag.get(fieldName);
if (stag != null) {
solitaireTag(writer, stag, value.stringValue());
continue;
}
// some special handling here
if (CollectionSchema.sku.getSolrFieldName().equals(fieldName)) {
url = writeLink(writer, value.stringValue());
continue;
}
if (CollectionSchema.title.getSolrFieldName().equals(fieldName)) {
docTitle = value.stringValue();
continue;
}
if (CollectionSchema.description_txt.getSolrFieldName().equals(fieldName)) {
String description = value.stringValue();
descriptions.add(description);
continue;
}
if (CollectionSchema.id.getSolrFieldName().equals(fieldName)) {
urlhash = value.stringValue();
solitaireTag(writer, "guid", urlhash);
continue;
}
if (CollectionSchema.url_paths_sxt.getSolrFieldName().equals(fieldName)) {
path.append('/').append(value.stringValue());
continue;
}
if (CollectionSchema.last_modified.getSolrFieldName().equals(fieldName)) {
Date d = new Date(Long.parseLong(value.stringValue()));
solitaireTag(writer, "pubDate", HeaderFramework.formatRFC1123(d));
continue;
}
if (CollectionSchema.size_i.getSolrFieldName().equals(fieldName)) {
int size = value.stringValue() != null && value.stringValue().length() > 0 ? Integer.parseInt(value.stringValue()) : -1;
writeSize(writer, size);
continue;
}
if (CollectionSchema.images_protocol_sxt.getSolrFieldName().equals(fieldName)) {
imagesProtocolObjs.add(value.stringValue());
continue;
}
if (CollectionSchema.images_urlstub_sxt.getSolrFieldName().equals(fieldName)) {
imagesStubs.add(value.stringValue());
continue;
}
//missing: "code","faviconCode"
}
writeDocEnd(writer, snippets, url, urlhash, descriptions, docTitle, path, imagesProtocolObjs,
imagesStubs);
} catch (final Exception ee) {
ConcurrentLog.logException(ee);
writer.write("\"description\":\"\"\n}\n");
}
writtenDocs++;
}
}
/**
* Append to the writer the YaCy json representation of Solr documents.
*
* @param writer an open output writer. Must not be null.
* @param documents the documents to render. Must not be null.
* @param responseCount the number of documents to process
* @param snippets snippets Solr computed text snippets (highlighting).
* @throws IOException when an unexpected error occurred while writing
*/
private void writeDocs(final Writer writer, final SolrDocumentList documents,
final Map<String, Collection<String>> snippets) throws IOException {
int writtenDocs = 0;
for (final SolrDocument doc : documents) {
if(writtenDocs > 0) {
writer.write(",\n".toCharArray());
}
try {
writer.write("{\n".toCharArray());
MultiProtocolURL url = null;
String urlhash = null;
List<String> descriptions = new ArrayList<>();
String docTitle = "";
StringBuilder path = new StringBuilder(80);
List<Object> imagesProtocolObjs = new ArrayList<>();
List<String> imagesStubs = new ArrayList<>();
for (final Entry<String, Object> fieldEntry : doc) {
final String fieldName = fieldEntry.getKey();
final Object value = fieldEntry.getValue();
if(value == null) {
continue;
}
// apply generic matching rule
String stag = field2tag.get(fieldName);
if (stag != null) {
solitaireTag(writer, stag, value.toString());
continue;
}
// some special handling here
if (CollectionSchema.sku.getSolrFieldName().equals(fieldName)) {
url = writeLink(writer, value.toString());
continue;
}
if (CollectionSchema.title.getSolrFieldName().equals(fieldName)) {
if(value instanceof Iterable<?>) {
/* Handle multivalued field */
for(final Object valueItem : (Iterable<?>)value) {
docTitle = valueItem.toString();
}
} else {
docTitle = value.toString();
}
continue;
}
if (CollectionSchema.description_txt.getSolrFieldName().equals(fieldName)) {
if(value instanceof Iterable<?>) {
/* Handle multivalued field */
for(final Object valueItem : (Iterable<?>)value) {
final String description = valueItem.toString();
descriptions.add(description);
}
} else {
final String description = value.toString();
descriptions.add(description);
}
continue;
}
if (CollectionSchema.id.getSolrFieldName().equals(fieldName)) {
urlhash = value.toString();
solitaireTag(writer, "guid", urlhash);
continue;
}
if (CollectionSchema.url_paths_sxt.getSolrFieldName().equals(fieldName)) {
if(value instanceof Iterable<?>) {
/* Handle multivalued field */
for(final Object valueItem : (Iterable<?>)value) {
path.append('/').append(valueItem.toString());
}
} else {
path.append('/').append(value.toString());
}
continue;
}
if (CollectionSchema.last_modified.getSolrFieldName().equals(fieldName) && value instanceof Date) {
solitaireTag(writer, "pubDate", HeaderFramework.formatRFC1123((Date)value));
continue;
}
if (CollectionSchema.size_i.getSolrFieldName().equals(fieldName) && value instanceof Integer) {
writeSize(writer, ((Integer)value).intValue());
continue;
}
if (CollectionSchema.images_protocol_sxt.getSolrFieldName().equals(fieldName)) {
if(value instanceof Iterable<?>) {
/* Handle multivalued field */
for(final Object valueItem : (Iterable<?>)value) {
imagesProtocolObjs.add(valueItem.toString());
}
} else {
imagesProtocolObjs.add(value.toString());
}
continue;
}
if (CollectionSchema.images_urlstub_sxt.getSolrFieldName().equals(fieldName)) {
if(value instanceof Iterable<?>) {
/* Handle multivalued field */
for(final Object valueItem : (Iterable<?>)value) {
imagesStubs.add(valueItem.toString());
}
} else {
imagesStubs.add(value.toString());
}
continue;
}
//missing: "code","faviconCode"
}
writeDocEnd(writer, snippets, url, urlhash, descriptions, docTitle, path, imagesProtocolObjs,
imagesStubs);
} catch (final Exception ee) {
ConcurrentLog.logException(ee);
writer.write("\"description\":\"\"\n}\n");
}
writtenDocs++;
}
}
/**
* Append information about the Solr document size to the writer
* @param writer an open output writer. Must not be null.
* @param size the size of the indexed document
* @throws IOException when an unexpected error occurred while writing
*/
private void writeSize(final Writer writer, int size) throws IOException {
int sizekb = size / 1024;
int sizemb = sizekb / 1024;
solitaireTag(writer, "size", Integer.toString(size));
solitaireTag(writer, "sizename", sizemb > 0 ? (Integer.toString(sizemb) + " mbyte") : sizekb > 0 ? (Integer.toString(sizekb) + " kbyte") : (Integer.toString(size) + " byte"));
}
/**
* Append information about the Solr document URL to the writer
* @param writer an open output writer. Must no be null.
* @param sku the Solr document URL as a String.
* @return a MultiProtocolURL instance built from the URL string, or null when the URL string is malformed.
* @throws IOException when an unexpected error occurred while writing
*/
private MultiProtocolURL writeLink(final Writer writer, final String sku)
throws IOException {
MultiProtocolURL url;
try {
url = new MultiProtocolURL(sku);
String filename = url.getFileName();
solitaireTag(writer, "link", sku);
solitaireTag(writer, "file", filename);
} catch (final MalformedURLException e) {
url = null;
}
return url;
}
/**
* Append to the writer the end of the YaCy json representation of the Solr
* document.
*/
private void writeDocEnd(final Writer writer, final Map<String, Collection<String>> snippets,
final MultiProtocolURL url, final String urlhash, final List<String> descriptions, final String docTitle, final StringBuilder path,
final List<Object> imagesProtocolObjs, final List<String> imagesStubs) throws IOException {
if (Math.min(imagesProtocolObjs.size(), imagesStubs.size()) > 0) {
List<String> imagesProtocols = CollectionConfiguration.indexedList2protocolList(imagesProtocolObjs, imagesStubs.size());
String imageurl = imagesProtocols.get(0) + "://" + imagesStubs.get(0);
solitaireTag(writer, "image", imageurl);
} else {
if (url != null && Response.docTypeExt(MultiProtocolURL.getFileExtension(url.getFile()).toLowerCase(Locale.ROOT)) == Response.DT_IMAGE) {
solitaireTag(writer, "image", url.toNormalform(true));
}
}
// compute snippet from texts
solitaireTag(writer, "path", path.toString());
solitaireTag(writer, "title", docTitle.length() == 0 ? path.toString() : docTitle.replaceAll("\"", "'"));
Collection<String> snippet = urlhash == null ? null : snippets.get(urlhash);
if (snippet == null) {snippet = new LinkedHashSet<>(); snippet.addAll(descriptions);}
OpensearchResponseWriter.removeSubsumedTitle(snippet, docTitle);
String snippetstring = snippet == null || snippet.size() == 0 ? (descriptions.size() > 0 ? descriptions.get(0) : "") : OpensearchResponseWriter.getLargestSnippet(snippet);
if (snippetstring != null && snippetstring.length() > 140) {
snippetstring = snippetstring.substring(0, 140);
int sp = snippetstring.lastIndexOf(' ');
if (sp >= 0) snippetstring = snippetstring.substring(0, sp) + " ..."; else snippetstring = snippetstring + "...";
}
writer.write("\"description\":"); writer.write(JSONObject.quote(snippetstring)); writer.write("\n}\n");
}
public static void solitaireTag(final Writer writer, final String tagname, String value) throws IOException {
if (value == null) return;
writer.write('"'); writer.write(tagname); writer.write("\":"); writer.write(JSONObject.quote(value)); writer.write(','); writer.write('\n');
}
private static void facetEntry(final Writer writer, String modifier, String propname, final String value) throws IOException {
modifier = modifier.replaceAll("\"", "'").trim();
propname = propname.replaceAll("\"", "'").trim();
writer.write("{\"name\":"); writer.write(JSONObject.quote(propname));
writer.write(",\"count\":"); writer.write(JSONObject.quote(value.replaceAll("\"", "'").trim()));
writer.write(",\"modifier\":"); writer.write(JSONObject.quote(modifier+"%3A"+propname));
writer.write("}");
}
}
/**
{
"channels": [{
"title": "YaCy P2P-Search for uni-mainz",
"description": "Search for uni-mainz",
"link": "http://localhost:8090/yacysearch.html?query=uni-mainz&resource=local&contentdom=text&verify=-UNRESOLVED_PATTERN-",
"image": {
"url": "http://localhost:8090/env/grafics/yacy.gif",
"title": "Search for uni-mainz",
"link": "http://localhost:8090/yacysearch.html?query=uni-mainz&resource=local&contentdom=text&verify=-UNRESOLVED_PATTERN-"
},
"totalResults": "1986",
"startIndex": "0",
"itemsPerPage": "10",
"searchTerms": "uni-mainz",
"items": [
{
"title": "From dark matter to school experiments: Physicists meet in Mainz",
"link": "http://www.phmi.uni-mainz.de/5305.php",
"code": "",
"description": "",
"pubDate": "Mon, 10 Sep 2012 10:25:36 +0000",
"size": "15927",
"sizename": "15 kbyte",
"guid": "7NYsT4NwCWgB",
"faviconCode": "d6ce1c0b",
"host": "www.phmi.uni-mainz.de",
"path": "/5305.php",
"file": "/5305.php",
"urlhash": "7NYsT4NwCWgB",
"ranking": "6983282"
}
,
..
}],
"navigation": [
{
"facetname": "filetypes",
"displayname": "Filetype",
"type": "String",
"min": "0",
"max": "0",
"mean": "0",
"elements": [
{"name": "php", "count": "8", "modifier": "filetype%3Aphp", "url": "/yacysearch.json?query=uni-mainz+filetype%3Aphp&maximumRecords=10&resource=local&verify=iffresh&nav=hosts,authors,namespace,topics,filetype,protocol&urlmaskfilter=.*&prefermaskfilter=&cat=href&constraint=&contentdom=text&former=uni-mainz&startRecord=0"},
{"name": "html", "count": "1", "modifier": "filetype%3Ahtml", "url": "/yacysearch.json?query=uni-mainz+filetype%3Ahtml&maximumRecords=10&resource=local&verify=iffresh&nav=hosts,authors,namespace,topics,filetype,protocol&urlmaskfilter=.*&prefermaskfilter=&cat=href&constraint=&contentdom=text&former=uni-mainz&startRecord=0"}
]
},
{
"facetname": "protocols",
"displayname": "Protocol",
"type": "String",
"min": "0",
"max": "0",
"mean": "0",
"elements": [
{"name": "http", "count": "13", "modifier": "%2Fhttp", "url": "/yacysearch.json?query=uni-mainz+%2Fhttp&maximumRecords=10&resource=local&verify=iffresh&nav=hosts,authors,namespace,topics,filetype,protocol&urlmaskfilter=.*&prefermaskfilter=&cat=href&constraint=&contentdom=text&former=uni-mainz&startRecord=0"},
{"name": "https", "count": "1", "modifier": "%2Fhttps", "url": "/yacysearch.json?query=uni-mainz+%2Fhttps&maximumRecords=10&resource=local&verify=iffresh&nav=hosts,authors,namespace,topics,filetype,protocol&urlmaskfilter=.*&prefermaskfilter=&cat=href&constraint=&contentdom=text&former=uni-mainz&startRecord=0"}
]
},
{
"facetname": "domains",
"displayname": "Domains",
"type": "String",
"min": "0",
"max": "0",
"mean": "0",
"elements": [
{"name": "www.geo.uni-frankfurt.de", "count": "1", "modifier": "site%3Awww.geo.uni-frankfurt.de", "url": "/yacysearch.json?query=uni-mainz+site%3Awww.geo.uni-frankfurt.de&maximumRecords=10&resource=local&verify=iffresh&nav=hosts,authors,namespace,topics,filetype,protocol&urlmaskfilter=.*&prefermaskfilter=&cat=href&constraint=&contentdom=text&former=uni-mainz&startRecord=0"},
{"name": "www.info.jogustine.uni-mainz.de", "count": "1", "modifier": "site%3Awww.info.jogustine.uni-mainz.de", "url": "/yacysearch.json?query=uni-mainz+site%3Awww.info.jogustine.uni-mainz.de&maximumRecords=10&resource=local&verify=iffresh&nav=hosts,authors,namespace,topics,filetype,protocol&urlmaskfilter=.*&prefermaskfilter=&cat=href&constraint=&contentdom=text&former=uni-mainz&startRecord=0"},
{"name": "www.fb09.uni-mainz.de", "count": "1", "modifier": "site%3Awww.fb09.uni-mainz.de", "url": "/yacysearch.json?query=uni-mainz+site%3Awww.fb09.uni-mainz.de&maximumRecords=10&resource=local&verify=iffresh&nav=hosts,authors,namespace,topics,filetype,protocol&urlmaskfilter=.*&prefermaskfilter=&cat=href&constraint=&contentdom=text&former=uni-mainz&startRecord=0"},
{"name": "www.studgen.uni-mainz.de", "count": "1", "modifier": "site%3Awww.studgen.uni-mainz.de", "url": "/yacysearch.json?query=uni-mainz+site%3Awww.studgen.uni-mainz.de&maximumRecords=10&resource=local&verify=iffresh&nav=hosts,authors,namespace,topics,filetype,protocol&urlmaskfilter=.*&prefermaskfilter=&cat=href&constraint=&contentdom=text&former=uni-mainz&startRecord=0"},
{"name": "twitter.com", "count": "1", "modifier": "site%3Atwitter.com", "url": "/yacysearch.json?query=uni-mainz+site%3Atwitter.com&maximumRecords=10&resource=local&verify=iffresh&nav=hosts,authors,namespace,topics,filetype,protocol&urlmaskfilter=.*&prefermaskfilter=&cat=href&constraint=&contentdom=text&former=uni-mainz&startRecord=0"},
{"name": "www.theaterwissenschaft.uni-mainz.de", "count": "1", "modifier": "site%3Awww.theaterwissenschaft.uni-mainz.de", "url": "/yacysearch.json?query=uni-mainz+site%3Awww.theaterwissenschaft.uni-mainz.de&maximumRecords=10&resource=local&verify=iffresh&nav=hosts,authors,namespace,topics,filetype,protocol&urlmaskfilter=.*&prefermaskfilter=&cat=href&constraint=&contentdom=text&former=uni-mainz&startRecord=0"},
{"name": "www.uni-mainz.de", "count": "1", "modifier": "site%3Awww.uni-mainz.de", "url": "/yacysearch.json?query=uni-mainz+site%3Awww.uni-mainz.de&maximumRecords=10&resource=local&verify=iffresh&nav=hosts,authors,namespace,topics,filetype,protocol&urlmaskfilter=.*&prefermaskfilter=&cat=href&constraint=&contentdom=text&former=uni-mainz&startRecord=0"},
{"name": "www.fb06.uni-mainz.de", "count": "1", "modifier": "site%3Awww.fb06.uni-mainz.de", "url": "/yacysearch.json?query=uni-mainz+site%3Awww.fb06.uni-mainz.de&maximumRecords=10&resource=local&verify=iffresh&nav=hosts,authors,namespace,topics,filetype,protocol&urlmaskfilter=.*&prefermaskfilter=&cat=href&constraint=&contentdom=text&former=uni-mainz&startRecord=0"},
{"name": "www.familienservice.uni-mainz.de", "count": "1", "modifier": "site%3Awww.familienservice.uni-mainz.de", "url": "/yacysearch.json?query=uni-mainz+site%3Awww.familienservice.uni-mainz.de&maximumRecords=10&resource=local&verify=iffresh&nav=hosts,authors,namespace,topics,filetype,protocol&urlmaskfilter=.*&prefermaskfilter=&cat=href&constraint=&contentdom=text&former=uni-mainz&startRecord=0"},
{"name": "www.zdv.uni-mainz.de", "count": "1", "modifier": "site%3Awww.zdv.uni-mainz.de", "url": "/yacysearch.json?query=uni-mainz+site%3Awww.zdv.uni-mainz.de&maximumRecords=10&resource=local&verify=iffresh&nav=hosts,authors,namespace,topics,filetype,protocol&urlmaskfilter=.*&prefermaskfilter=&cat=href&constraint=&contentdom=text&former=uni-mainz&startRecord=0"},
{"name": "zope.verwaltung.uni-mainz.de", "count": "1", "modifier": "site%3Azope.verwaltung.uni-mainz.de", "url": "/yacysearch.json?query=uni-mainz+site%3Azope.verwaltung.uni-mainz.de&maximumRecords=10&resource=local&verify=iffresh&nav=hosts,authors,namespace,topics,filetype,protocol&urlmaskfilter=.*&prefermaskfilter=&cat=href&constraint=&contentdom=text&former=uni-mainz&startRecord=0"},
{"name": "www.geo.uni-mainz.de", "count": "1", "modifier": "site%3Awww.geo.uni-mainz.de", "url": "/yacysearch.json?query=uni-mainz+site%3Awww.geo.uni-mainz.de&maximumRecords=10&resource=local&verify=iffresh&nav=hosts,authors,namespace,topics,filetype,protocol&urlmaskfilter=.*&prefermaskfilter=&cat=href&constraint=&contentdom=text&former=uni-mainz&startRecord=0"},
{"name": "www.bio.uni-mainz.de", "count": "1", "modifier": "site%3Awww.bio.uni-mainz.de", "url": "/yacysearch.json?query=uni-mainz+site%3Awww.bio.uni-mainz.de&maximumRecords=10&resource=local&verify=iffresh&nav=hosts,authors,namespace,topics,filetype,protocol&urlmaskfilter=.*&prefermaskfilter=&cat=href&constraint=&contentdom=text&former=uni-mainz&startRecord=0"},
{"name": "www.phmi.uni-mainz.de", "count": "1", "modifier": "site%3Awww.phmi.uni-mainz.de", "url": "/yacysearch.json?query=uni-mainz+site%3Awww.phmi.uni-mainz.de&maximumRecords=10&resource=local&verify=iffresh&nav=hosts,authors,namespace,topics,filetype,protocol&urlmaskfilter=.*&prefermaskfilter=&cat=href&constraint=&contentdom=text&former=uni-mainz&startRecord=0"}
]
},
{
"facetname": "topics",
"displayname": "Topics",
"type": "String",
"min": "0",
"max": "0",
"mean": "0",
"elements": [
{"name": "des", "count": "3", "modifier": "des", "url": "/yacysearch.json?query=uni-mainz+des&maximumRecords=10&resource=local&verify=iffresh&nav=hosts,authors,namespace,topics,filetype,protocol&urlmaskfilter=.*&prefermaskfilter=&cat=href&constraint=&contentdom=text&former=uni-mainz&startRecord=0"},
{"name": "auf", "count": "2", "modifier": "auf", "url": "/yacysearch.json?query=uni-mainz+auf&maximumRecords=10&resource=local&verify=iffresh&nav=hosts,authors,namespace,topics,filetype,protocol&urlmaskfilter=.*&prefermaskfilter=&cat=href&constraint=&contentdom=text&former=uni-mainz&startRecord=0"},
{"name": "willkommen", "count": "2", "modifier": "willkommen", "url": "/yacysearch.json?query=uni-mainz+willkommen&maximumRecords=10&resource=local&verify=iffresh&nav=hosts,authors,namespace,topics,filetype,protocol&urlmaskfilter=.*&prefermaskfilter=&cat=href&constraint=&contentdom=text&former=uni-mainz&startRecord=0"},
{"name": "biologie", "count": "1", "modifier": "biologie", "url": "/yacysearch.json?query=uni-mainz+biologie&maximumRecords=10&resource=local&verify=iffresh&nav=hosts,authors,namespace,topics,filetype,protocol&urlmaskfilter=.*&prefermaskfilter=&cat=href&constraint=&contentdom=text&former=uni-mainz&startRecord=0"},
{"name": "johannes", "count": "1", "modifier": "johannes", "url": "/yacysearch.json?query=uni-mainz+johannes&maximumRecords=10&resource=local&verify=iffresh&nav=hosts,authors,namespace,topics,filetype,protocol&urlmaskfilter=.*&prefermaskfilter=&cat=href&constraint=&contentdom=text&former=uni-mainz&startRecord=0"},
{"name": "weiterleitung", "count": "1", "modifier": "weiterleitung", "url": "/yacysearch.json?query=uni-mainz+weiterleitung&maximumRecords=10&resource=local&verify=iffresh&nav=hosts,authors,namespace,topics,filetype,protocol&urlmaskfilter=.*&prefermaskfilter=&cat=href&constraint=&contentdom=text&former=uni-mainz&startRecord=0"},
{"name": "archiv", "count": "1", "modifier": "archiv", "url": "/yacysearch.json?query=uni-mainz+archiv&maximumRecords=10&resource=local&verify=iffresh&nav=hosts,authors,namespace,topics,filetype,protocol&urlmaskfilter=.*&prefermaskfilter=&cat=href&constraint=&contentdom=text&former=uni-mainz&startRecord=0"},
{"name": "entdecken", "count": "1", "modifier": "entdecken", "url": "/yacysearch.json?query=uni-mainz+entdecken&maximumRecords=10&resource=local&verify=iffresh&nav=hosts,authors,namespace,topics,filetype,protocol&urlmaskfilter=.*&prefermaskfilter=&cat=href&constraint=&contentdom=text&former=uni-mainz&startRecord=0"},
{"name": "gutenberg", "count": "1", "modifier": "gutenberg", "url": "/yacysearch.json?query=uni-mainz+gutenberg&maximumRecords=10&resource=local&verify=iffresh&nav=hosts,authors,namespace,topics,filetype,protocol&urlmaskfilter=.*&prefermaskfilter=&cat=href&constraint=&contentdom=text&former=uni-mainz&startRecord=0"},
{"name": "heimverzeichnis", "count": "1", "modifier": "heimverzeichnis", "url": "/yacysearch.json?query=uni-mainz+heimverzeichnis&maximumRecords=10&resource=local&verify=iffresh&nav=hosts,authors,namespace,topics,filetype,protocol&urlmaskfilter=.*&prefermaskfilter=&cat=href&constraint=&contentdom=text&former=uni-mainz&startRecord=0"},
{"name": "school", "count": "1", "modifier": "school", "url": "/yacysearch.json?query=uni-mainz+school&maximumRecords=10&resource=local&verify=iffresh&nav=hosts,authors,namespace,topics,filetype,protocol&urlmaskfilter=.*&prefermaskfilter=&cat=href&constraint=&contentdom=text&former=uni-mainz&startRecord=0"},
{"name": "vernetzung", "count": "1", "modifier": "vernetzung", "url": "/yacysearch.json?query=uni-mainz+vernetzung&maximumRecords=10&resource=local&verify=iffresh&nav=hosts,authors,namespace,topics,filetype,protocol&urlmaskfilter=.*&prefermaskfilter=&cat=href&constraint=&contentdom=text&former=uni-mainz&startRecord=0"}
]
}
],
"totalResults": "1986"
}]
}
*/