From: Adam Dickmeiss Date: Mon, 3 Dec 2007 11:49:11 +0000 (+0000) Subject: First functional facet result (zebra::facet::..). X-Git-Tag: ZEBRA.2.0.20~44 X-Git-Url: http://git.indexdata.com/?p=idzebra-moved-to-github.git;a=commitdiff_plain;h=ebc8a5296010dd0379bf7ae81b6c31145f8e85a7 First functional facet result (zebra::facet::..). --- diff --git a/index/index.h b/index/index.h index 2bbb61a..bc631cf 100644 --- a/index/index.h +++ b/index/index.h @@ -1,4 +1,4 @@ -/* $Id: index.h,v 1.210 2007-11-30 12:19:08 adam Exp $ +/* $Id: index.h,v 1.211 2007-12-03 11:49:11 adam Exp $ Copyright (C) 1995-2007 Index Data ApS @@ -449,6 +449,9 @@ ZEBRA_RES zebra_result_recid_to_sysno(ZebraHandle zh, zint recid, zint *sysnos, int *no_sysnos); +void zebra_count_set(ZebraHandle zh, RSET rset, zint *count, + zint approx_limit); + YAZ_END_CDECL #endif diff --git a/index/retrieve.c b/index/retrieve.c index 364bd23..70d0da2 100644 --- a/index/retrieve.c +++ b/index/retrieve.c @@ -1,4 +1,4 @@ -/* $Id: retrieve.c,v 1.76 2007-11-30 12:19:08 adam Exp $ +/* $Id: retrieve.c,v 1.77 2007-12-03 11:49:11 adam Exp $ Copyright (C) 1995-2007 Index Data ApS @@ -37,6 +37,9 @@ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA #include #include #include +#include + +#define MAX_SYSNOS_PER_RECORD 40 #define ZEBRA_XML_HEADER_STR "index_type = 0; + spec->next = 0; + + if (!first) + first = spec; + *last = spec; + last = &spec->next; + + cp++; /* skip ',' or second ':' */ + cp0 = cp; + while (*cp != ':' && *cp != '\0' && *cp != ',') + cp++; + spec->index_name = nmem_strdupn(nmem, cp0, cp - cp0); + if (*cp == ':') /* type as well */ + { + cp++; + cp0 = cp; + + while (*cp != '\0' && *cp != ',') + cp++; + spec->index_type = nmem_strdupn(nmem, cp0, cp - cp0); + } + if (*cp != ',') + break; + } + } + if (*cp != '\0') + *error = 1; + return first; +} + static int parse_zebra_elem(const char *elem, const char **index, size_t *index_len, const char **type, size_t *type_len) @@ -352,7 +409,6 @@ int zebra_special_index_fetch(ZebraHandle zh, zint sysno, ODR odr, wrbuf_printf(wrbuf, " " ZINT_FORMAT, key_in.mem[i]); - /* zebra_term_untrans(zh, index_type, dst_buf, str); */ wrbuf_printf(wrbuf, " %s", dst_buf); wrbuf_printf(wrbuf, "\n"); @@ -484,12 +540,12 @@ int zebra_get_rec_snippets(ZebraHandle zh, zint sysno, return return_code; } -int zebra_special_snippet_fetch(ZebraHandle zh, const char *setname, - zint sysno, ODR odr, - const char *elemsetname, - const Odr_oid *input_format, - const Odr_oid **output_format, - char **rec_bufp, int *rec_lenp) +static int snippet_fetch(ZebraHandle zh, const char *setname, + zint sysno, ODR odr, + const char *elemsetname, + const Odr_oid *input_format, + const Odr_oid **output_format, + char **rec_bufp, int *rec_lenp) { zebra_snippets *rec_snippets = zebra_snippets_create(); int return_code = zebra_get_rec_snippets(zh, sysno, rec_snippets); @@ -534,6 +590,262 @@ int zebra_special_snippet_fetch(ZebraHandle zh, const char *setname, return return_code; } +struct term_collect { + const char *term; + int oc; + zint set_occur; +}; + +zint freq_term(ZebraHandle zh, int ord, const char *term, RSET rset_set) +{ + struct rset_key_control *kc = zebra_key_control_create(zh); + char ord_buf[IT_MAX_WORD]; + int ord_len = key_SU_encode(ord, ord_buf); + char *info; + zint hits = 0; + NMEM nmem = nmem_create(); + + strcpy(ord_buf + ord_len, term); + + info = dict_lookup(zh->reg->dict, ord_buf); + if (info) + { + ISAM_P isam_p; + RSET rsets[2], rset; + memcpy(&isam_p, info+1, sizeof(ISAM_P)); + + rsets[0] = rsisamb_create(nmem, kc, + 2, zh->reg->isamb, isam_p, 0); + rsets[1] = rset_dup(rset_set); + + rset = rset_create_and(nmem, kc, kc->scope, 2, rsets); + + zebra_count_set(zh, rset, &hits, zh->approx_limit); + + rset_delete(rsets[0]); + rset_delete(rset); + } + (*kc->dec)(kc); + nmem_destroy(nmem); + return hits; +} + +void term_collect_freq(ZebraHandle zh, + struct term_collect *col, int no_terms_collect, + int ord, RSET rset) +{ + int i; + for (i = 0; i < no_terms_collect; i++) + { + if (col[i].term) + col[i].set_occur = freq_term(zh, ord, col[i].term, rset); + } +} + +struct term_collect *term_collect_create(zebra_strmap_t sm, + int no_terms_collect, + NMEM nmem) +{ + const char *term; + void *data_buf; + size_t data_len; + zebra_strmap_it it; + struct term_collect *col = nmem_malloc(nmem, + sizeof *col *no_terms_collect); + int i; + for (i = 0; i < no_terms_collect; i++) + { + col[i].term = 0; + col[i].oc = 0; + col[i].set_occur = 0; + } + /* iterate over terms and collect the most frequent ones */ + it = zebra_strmap_it_create(sm); + while ((term = zebra_strmap_it_next(it, &data_buf, &data_len))) + { + int oc = *(int*) data_buf; + int j = 0; + /* insertion may be slow but terms terms will be "infrequent" and + thus number of iterations should be small below */ + while (j < no_terms_collect && oc > col[j].oc) + j++; + if (j) + { + --j; + memmove(col, col+1, sizeof(*col) * j); + col[j].term = term; + col[j].oc = oc; + } + } + zebra_strmap_it_destroy(it); + return col; +} + +static ZEBRA_RES facet_fetch(ZebraHandle zh, const char *setname, + ODR odr, + const char *elemsetname, + const Odr_oid *input_format, + const Odr_oid **output_format, + char **rec_bufp, int *rec_lenp) +{ + zint *pos_array; + int i; + int num_recs = 10; /* number of records to analyze */ + int no_collect_terms = 20; /* number of term candidates */ + ZebraMetaRecord *poset; + ZEBRA_RES ret = ZEBRA_OK; + int *ord_array; + WRBUF wr = wrbuf_alloc(); + + int no_ord = 0; + struct index_spec *spec, *spec_list; + int error; + + + spec_list = parse_index_spec(elemsetname, odr_getmem(odr), &error); + + if (!spec_list || error) + return YAZ_BIB1_SPECIFIED_ELEMENT_SET_NAME_NOT_VALID_FOR_SPECIFIED_; + + for (spec = spec_list; spec; spec = spec->next) + { + if (!spec->index_type) + return YAZ_BIB1_SPECIFIED_ELEMENT_SET_NAME_NOT_VALID_FOR_SPECIFIED_; + no_ord++; + } + + ord_array = odr_malloc(odr, sizeof(*ord_array) * no_ord); + + for (spec = spec_list, i = 0; spec; spec = spec->next, i++) + { + int ord = zebraExplain_lookup_attr_str(zh->reg->zei, + zinfo_index_category_index, + spec->index_type, + spec->index_name); + if (ord == -1) + { + return YAZ_BIB1_SPECIFIED_ELEMENT_SET_NAME_NOT_VALID_FOR_SPECIFIED_; + } + ord_array[i] = ord; + } + + pos_array = (zint *) xmalloc(num_recs * sizeof(*pos_array)); + for (i = 0; i < num_recs; i++) + pos_array[i] = i+1; + poset = zebra_meta_records_create(zh, setname, num_recs, pos_array); + if (!poset) + { + zebra_setError(zh, YAZ_BIB1_SPECIFIED_RESULT_SET_DOES_NOT_EXIST, + setname); + xfree(pos_array); + ret = ZEBRA_FAIL; + } + else + { + zebra_strmap_t *map_array + = odr_malloc(odr, sizeof *map_array * no_ord); + for (i = 0; i < no_ord; i++) + map_array[i] = zebra_strmap_create(); + + for (i = 0; i < num_recs; i++) + { + int j; + zint sysnos[MAX_SYSNOS_PER_RECORD]; + int no_sysnos = MAX_SYSNOS_PER_RECORD; + if (!poset[i].sysno) + continue; + ret = zebra_result_recid_to_sysno(zh, setname, + poset[i].sysno, + sysnos, &no_sysnos); + assert(no_sysnos > 0); + for (j = 0; j < no_sysnos; j++) + { + size_t slen; + const char *str; + struct it_key key_in; + Record rec = rec_get(zh->reg->records, sysnos[j]); + zebra_rec_keys_t keys = zebra_rec_keys_open(); + zebra_rec_keys_set_buf(keys, rec->info[recInfo_delKeys], + rec->size[recInfo_delKeys], 0); + + if (zebra_rec_keys_rewind(keys)) + { + while (zebra_rec_keys_read(keys, &str, &slen, &key_in)) + { + int i; + struct index_spec *spec; + for (spec = spec_list, i = 0; i < no_ord; + i++, spec = spec->next) + { + int ord = CAST_ZINT_TO_INT(key_in.mem[0]); + if (ord == ord_array[i]) + { + int *freq; + zebra_strmap_t sm = map_array[i]; + + freq = zebra_strmap_lookup(sm, str, 0, 0); + if (freq) + (*freq)++; + else + { + int v = 1; + zebra_strmap_add(sm, str, &v, sizeof v); + } + } + } + } + } + zebra_rec_keys_close(keys); + rec_free(&rec); + } + } + wrbuf_puts(wr, "\n"); + for (spec = spec_list, i = 0; i < no_ord; i++, spec = spec->next) + { + int j; + NMEM nmem = nmem_create(); + struct term_collect *col = term_collect_create(map_array[i], + no_collect_terms, + nmem); + term_collect_freq(zh, col, no_collect_terms, ord_array[i], + resultSetRef(zh, setname)); + + wrbuf_printf(wr, " \n", + spec->index_type, spec->index_name); + for (j = 0; j < no_collect_terms; j++) + { + if (col[j].term) + { + char dst_buf[IT_MAX_WORD]; + zebra_term_untrans(zh, spec->index_type, dst_buf, col[j].term); + wrbuf_printf(wr, " "); + wrbuf_xmlputs(wr, dst_buf); + wrbuf_printf(wr, "\n"); + } + } + wrbuf_puts(wr, " \n"); + nmem_destroy(nmem); + } + wrbuf_puts(wr, "\n"); + for (i = 0; i < no_ord; i++) + zebra_strmap_destroy(map_array[i]); + } + + + *rec_bufp = odr_strdup(odr, wrbuf_cstr(wr)); + wrbuf_destroy(wr); + *rec_lenp = strlen(*rec_bufp); + *output_format = input_format; + + xfree(pos_array); + zebra_meta_records_destroy(zh, poset, num_recs); + return ret; +} + int zebra_special_fetch(ZebraHandle zh, const char *setname, zint sysno, int score, ODR odr, const char *elemsetname, @@ -546,13 +858,20 @@ int zebra_special_fetch(ZebraHandle zh, const char *setname, /* set output variables before processing possible error states */ /* *rec_lenp = 0; */ + if (elemsetname && 0 == strncmp(elemsetname, "facet", 5)) + { + return facet_fetch(zh, setname, odr, + elemsetname + 5, + input_format, output_format, + rec_bufp, rec_lenp); + } if (elemsetname && 0 == strcmp(elemsetname, "snippet")) { - return zebra_special_snippet_fetch(zh, setname, sysno, odr, - elemsetname + 7, - input_format, output_format, - rec_bufp, rec_lenp); + return snippet_fetch(zh, setname, sysno, odr, + elemsetname + 7, + input_format, output_format, + rec_bufp, rec_lenp); } /* processing zebra::meta::sysno elemset without fetching binary data */ @@ -716,8 +1035,8 @@ int zebra_record_fetch(ZebraHandle zh, const char *setname, RecordAttr *recordAttr; void *clientData; int return_code = 0; - zint sysnos[10]; - int no_sysnos = 10; + zint sysnos[MAX_SYSNOS_PER_RECORD]; + int no_sysnos = MAX_SYSNOS_PER_RECORD; ZEBRA_RES res; res = zebra_result_recid_to_sysno(zh, setname, sysno, sysnos, &no_sysnos); diff --git a/index/rpnscan.c b/index/rpnscan.c index 6d575df..3312157 100644 --- a/index/rpnscan.c +++ b/index/rpnscan.c @@ -1,4 +1,4 @@ -/* $Id: rpnscan.c,v 1.22 2007-11-13 13:41:51 adam Exp $ +/* $Id: rpnscan.c,v 1.23 2007-12-03 11:49:11 adam Exp $ Copyright (C) 1995-2007 Index Data ApS @@ -79,31 +79,6 @@ static ZEBRA_RES trans_scan_term(ZebraHandle zh, Z_AttributesPlusTerm *zapt, return ZEBRA_OK; } -static void count_set(ZebraHandle zh, RSET rset, zint *count, zint approx_limit) -{ - zint psysno = 0; - struct it_key key; - RSFD rfd; - - yaz_log(YLOG_DEBUG, "count_set"); - - rset->hits_limit = approx_limit; - - *count = 0; - rfd = rset_open(rset, RSETF_READ); - while (rset_read(rfd, &key,0 /* never mind terms */)) - { - if (key.mem[0] != psysno) - { - psysno = key.mem[0]; - if (rfd->counted_items >= rset->hits_limit) - break; - } - } - rset_close(rfd); - *count = rset->hits_count; -} - static void get_first_snippet_from_rset(ZebraHandle zh, RSET rset, zebra_snippets *snippets, zint *sysno) @@ -238,7 +213,7 @@ static int scan_save_set(ZebraHandle zh, ODR stream, NMEM nmem, rset = rset_create_and(nmem, kc, kc->scope, 2, rsets); } /* count it */ - count_set(zh, rset, &count, approx_limit); + zebra_count_set(zh, rset, &count, approx_limit); if (pos != -1) { diff --git a/index/zsets.c b/index/zsets.c index 19fb36a..8810246 100644 --- a/index/zsets.c +++ b/index/zsets.c @@ -1,4 +1,4 @@ -/* $Id: zsets.c,v 1.127 2007-12-01 21:34:10 adam Exp $ +/* $Id: zsets.c,v 1.128 2007-12-03 11:49:11 adam Exp $ Copyright (C) 1995-2007 Index Data ApS @@ -1403,6 +1403,32 @@ ZEBRA_RES zebra_result_recid_to_sysno(ZebraHandle zh, return zebra_recid_to_sysno(zh, basenames, num_bases, recid, sysnos, no_sysnos); } + +void zebra_count_set(ZebraHandle zh, RSET rset, zint *count, + zint approx_limit) +{ + zint psysno = 0; + struct it_key key; + RSFD rfd; + + yaz_log(YLOG_DEBUG, "count_set"); + + rset->hits_limit = approx_limit; + + *count = 0; + rfd = rset_open(rset, RSETF_READ); + while (rset_read(rfd, &key,0 /* never mind terms */)) + { + if (key.mem[0] != psysno) + { + psysno = key.mem[0]; + if (rfd->counted_items >= rset->hits_limit) + break; + } + } + rset_close(rfd); + *count = rset->hits_count; +} /* diff --git a/test/api/safari1.c b/test/api/safari1.c index 0b311c5..20d8481 100644 --- a/test/api/safari1.c +++ b/test/api/safari1.c @@ -1,4 +1,4 @@ -/* $Id: safari1.c,v 1.19 2007-11-30 12:19:09 adam Exp $ +/* $Id: safari1.c,v 1.20 2007-12-03 11:49:12 adam Exp $ Copyright (C) 1995-2007 Index Data ApS @@ -96,12 +96,27 @@ static void tst(int argc, char **argv) ids[2] = 24340; YAZ_CHECK(tl_meta_query(zh, "@attr 4=3 @attr 1=any mand", 3, ids)); +#if 1 YAZ_CHECK_EQ(tl_fetch_compare(zh, 1, "R", yaz_oid_recsyn_sutrs, myrec[0]), ZEBRA_OK); YAZ_CHECK_EQ(tl_fetch_compare(zh, 2, "R", yaz_oid_recsyn_sutrs, myrec[2]), ZEBRA_OK); YAZ_CHECK_EQ(tl_fetch_compare(zh, 3, "R", yaz_oid_recsyn_sutrs, myrec[4]), ZEBRA_OK); +#endif +#if 1 + YAZ_CHECK_EQ(tl_fetch_compare(zh, 1, "zebra::facet::any:0", + yaz_oid_recsyn_sutrs, + "\n" + " \n" + " old\n" + " art\n" + " gamle\n" + " mand\n" + " the\n" + " \n" + "\n"), ZEBRA_OK); +#endif /* limit to 125061 */ limits[0] = 125061; limits[1] = 0;