X-Git-Url: http://git.indexdata.com/?a=blobdiff_plain;f=src%2Fsolr.c;h=16c5fa61a5e557037a217d1cba8073ec4fa53a24;hb=3c287bc1d48ee6a1f300054c2cebd0ba312bd5b9;hp=b8639f1ce13a0fd2ab481d62fb2c7d7c33571bf1;hpb=fc405db33968e9d67cfc066cdfcee2b8bdae6164;p=yaz-moved-to-github.git diff --git a/src/solr.c b/src/solr.c index b8639f1..16c5fa6 100644 --- a/src/solr.c +++ b/src/solr.c @@ -4,7 +4,7 @@ */ /** * \file solr.c - * \brief Implements SOAP Webservice decoding/encoding + * \brief Implements Solr decoding/encoding */ #if HAVE_CONFIG_H #include @@ -27,6 +27,15 @@ #include #include +static void extract_text_node(xmlNodePtr node, WRBUF wrbuf) { + xmlNodePtr child; + for (child = node->children; child ; child = child->next) + { + if (child->type == XML_TEXT_NODE) + wrbuf_puts(wrbuf, (const char *) child->content); + } +} + static int match_xml_node_attribute( xmlNodePtr ptr, const char *node_name, const char *attribute_name, const char *value) @@ -59,8 +68,9 @@ static void yaz_solr_decode_result_docs(ODR o, xmlNodePtr ptr, for (node = ptr->children; node; node = node->next) if (node->type == XML_ELEMENT_NODE) sr->num_records++; - - sr->records = odr_malloc(o, sizeof(*sr->records) * sr->num_records); + + if (sr->num_records) + sr->records = odr_malloc(o, sizeof(*sr->records) * sr->num_records); for (node = ptr->children; node; node = node->next) { @@ -117,7 +127,7 @@ static int yaz_solr_decode_result(ODR o, xmlNodePtr ptr, return -1; } -static const char *get_facet_term_count(xmlNodePtr node, int *freq) +static const char *get_facet_term_count(xmlNodePtr node, Odr_int *freq) { const char *term = yaz_element_attribute_value_get(node, "int", "name"); xmlNodePtr child; @@ -130,7 +140,7 @@ static const char *get_facet_term_count(xmlNodePtr node, int *freq) if (child->type == XML_TEXT_NODE) wrbuf_puts(wrbuf, (const char *) child->content); } - *freq = atoi(wrbuf_cstr(wrbuf)); + *freq = odr_atoi(wrbuf_cstr(wrbuf)); wrbuf_destroy(wrbuf); return term; } @@ -146,11 +156,6 @@ Z_FacetField *yaz_solr_decode_facet_field(ODR o, xmlNodePtr ptr, xmlNodePtr node; // USE attribute const char* name = yaz_element_attribute_value_get(ptr, "lst", "name"); - char *pos = strstr(name, "_exact"); - /* HACK */ - if (pos) { - pos[0] = 0; - } list = yaz_use_attribute_create(o, name); for (node = ptr->children; node; node = node->next) num_terms++; @@ -158,11 +163,10 @@ Z_FacetField *yaz_solr_decode_facet_field(ODR o, xmlNodePtr ptr, index = 0; for (node = ptr->children; node; node = node->next) { - int count = 0; + Odr_int count = 0; const char *term = get_facet_term_count(node, &count); facet_field_term_set(o, facet_field, - facet_term_create(o, term_create(o, term), count), - index); + facet_term_create_cstr(o, term, count), index); index++; } return facet_field; @@ -199,6 +203,64 @@ static int yaz_solr_decode_facet_counts(ODR o, xmlNodePtr root, return 0; } +static void yaz_solr_decode_suggestion_values(xmlNodePtr listPptr, WRBUF wrbuf) +{ + xmlNodePtr node; + for (node = listPptr; node; node= node->next) { + if (!strcmp((char*) node->name, "lst")) { + xmlNodePtr child; + for (child = node->children; child; child= child->next) { + if (match_xml_node_attribute(child, "str", "name", "word")) { + wrbuf_puts(wrbuf, ""); + extract_text_node(child, wrbuf); + wrbuf_puts(wrbuf, "\n"); + } + } + } + } +} + +static void yaz_solr_decode_suggestion_lst(xmlNodePtr lstPtr, WRBUF wrbuf) +{ + xmlNodePtr node; + for (node = lstPtr; node; node= node->next) { + if (match_xml_node_attribute(node, "arr", "name", "suggestion")) { + yaz_solr_decode_suggestion_values(node->children, wrbuf); + } + } +} + +static void yaz_solr_decode_misspelled(xmlNodePtr lstPtr, WRBUF wrbuf) +{ + xmlNodePtr node; + for (node = lstPtr; node; node= node->next) + { + if (!strcmp((const char*) node->name, "lst")) { + const char *misspelled = yaz_element_attribute_value_get(node, "lst", "name"); + if (misspelled) { + wrbuf_printf(wrbuf, "\n", misspelled); + yaz_solr_decode_suggestion_lst(node->children, wrbuf); + wrbuf_puts(wrbuf, "\n"); + } + } + } +} + +static int yaz_solr_decode_spellcheck(ODR o, xmlNodePtr spellcheckPtr, Z_SRW_searchRetrieveResponse *sr) +{ + xmlNodePtr ptr; + WRBUF wrbuf = wrbuf_alloc(); + wrbuf_puts(wrbuf, ""); + for (ptr = spellcheckPtr->children; ptr; ptr = ptr->next) + { + if (match_xml_node_attribute(ptr, "lst", "name", "suggestions")) + { + yaz_solr_decode_misspelled(ptr->children, wrbuf); + } + } + sr->suggestions = odr_strdup(o, wrbuf_cstr(wrbuf)); + return 0; +} #endif int yaz_solr_decode_response(ODR o, Z_HTTP_Response *hres, Z_SRW_PDU **pdup) @@ -240,9 +302,12 @@ int yaz_solr_decode_response(ODR o, Z_HTTP_Response *hres, Z_SRW_PDU **pdup) /* TODO The check on hits is a work-around to avoid garbled facets on zero results from the SOLR server. * The work-around works because the results is before the facets in the xml. */ if (rc_result == 0 && *sr->numberOfRecords > 0 && - match_xml_node_attribute(ptr, "lst", "name", - "facet_counts")) + match_xml_node_attribute(ptr, "lst", "name", "facet_counts")) rc_facets = yaz_solr_decode_facet_counts(o, ptr, sr); + if (rc_result == 0 && *sr->numberOfRecords == 0 && + match_xml_node_attribute(ptr, "lst", "name", "spellcheck")) + rc_facets = yaz_solr_decode_spellcheck(o, ptr, sr); + } ret = rc_result + rc_facets; } @@ -257,7 +322,7 @@ int yaz_solr_decode_response(ODR o, Z_HTTP_Response *hres, Z_SRW_PDU **pdup) #endif } -static void yaz_solr_encode_facet_field( +static int yaz_solr_encode_facet_field( ODR encode, char **name, char **value, int *i, Z_FacetField *facet_field) { @@ -266,13 +331,13 @@ static void yaz_solr_encode_facet_field( yaz_facet_attr_init(&attr_values); yaz_facet_attr_get_z_attributes(attribute_list, &attr_values); // TODO do we want to support server decided - if (!attr_values.errcode && attr_values.useattr) + + if (attr_values.errcode) + return -1; + if (attr_values.useattr) { WRBUF wrbuf = wrbuf_alloc(); wrbuf_puts(wrbuf, (char *) attr_values.useattr); - /* Skip date field */ - if (strcmp("date", attr_values.useattr) != 0) - wrbuf_puts(wrbuf, "_exact"); yaz_add_name_value_str(encode, name, value, i, "facet.field", odr_strdup(encode, wrbuf_cstr(wrbuf))); @@ -291,19 +356,23 @@ static void yaz_solr_encode_facet_field( } wrbuf_destroy(wrbuf); } + return 0; } -static void yaz_solr_encode_facet_list( +static int yaz_solr_encode_facet_list( ODR encode, char **name, char **value, int *i, Z_FacetList *facet_list) { int index; for (index = 0; index < facet_list->num; index++) { - yaz_solr_encode_facet_field(encode, name, value, i, - facet_list->elements[index]); + int r = yaz_solr_encode_facet_field(encode, name, value, i, + facet_list->elements[index]); + if (r) + return -1; } + return 0; } int yaz_solr_encode_request(Z_HTTP_Request *hreq, Z_SRW_PDU *srw_pdu, @@ -351,17 +420,26 @@ int yaz_solr_encode_request(Z_HTTP_Request *hreq, Z_SRW_PDU *srw_pdu, Z_FacetList *facet_list = request->facetList; yaz_add_name_value_str(encode, name, value, &i, "facet", "true"); yaz_add_name_value_str(encode, name, value, &i, "facet.mincount", "1"); - yaz_solr_encode_facet_list(encode, name, value, &i, facet_list); - /* - olimit = limit; - yaz_add_name_value_int(encode, name, value, &i, "facet.limit", &olimit); - */ - + if (yaz_solr_encode_facet_list(encode, name, value, &i, facet_list)) + return -1; } } else return -1; - name[i] = 0; + + if (srw_pdu->extra_args) + { + Z_SRW_extra_arg *ea = srw_pdu->extra_args; + for (; ea && i < SOLR_MAX_PARAMETERS; ea = ea->next) + { + name[i] = ea->name; + value[i] = ea->value; + i++; + } + } + + name[i++] = 0; + yaz_array_to_uri(&uri_args, encode, name, value); hreq->method = "GET";