Named Querylets

Complex query trees can be constructed using the score generator and score combiner querylets described in the Query Combiners section. By default only the scores from the top level querylet are returned. Usually this is all that is needed, but in some cases you might need to know the score returned by a lower level querylet. For example, consider a query to find a person where records contain several alternate names:

    And( Or( Simple("tom jones", { "first", "middle", "last" }),
Simple("tom jones", { "aka_1" }),
Simple("tom jones", { "aka_2" })
),
Simple("123 Walrus St", { "street" }),
Simple("Santa Cruz", { "city" }),
Simple("CA", { "state" })
)

In addition to the overall score, it would be good to know how well it matched on the primary "first", "middle", and "last" name fields. By default only the top level scores are returned. So there is the overall score and the top level querylet scores, but because the simple query for the names appears two levels down, you do not have access to the scores returned by these querylets. By assigning a name to these querylets you can retrieve the desired scores. The following example shows how to construct the above query assigning a name to each of the simple querylets for the name:

 

/* field names used by querylets */
unsigned char *name_fields[] = { "first", "middle", "last" };
unsigned char *aka1_fields[] = { "aka1" } ;
unsigned char *aka2_fields[] = { "aka2" } ;
unsigned char *street_fields[] = { "street" } ;
unsigned char *city_fields[] = { "city" } ;
unsigned char *state_fields[] = { "state" } ;
/* our search values */
const unsigned char *name_value = (const unsigned char *)"tom jones" ;
const unsigned char *street_value = (const unsigned char *)"123 Walrus St" ;
const unsigned char *city_value = (const unsigned char *)"Santa Cruz" ;
const unsigned char *state_value = (const unsigned char *)"CA" ;
/* our query lpar's */
lpar_t name_query ;
lpar_t street_query ;
lpar_t city_query ;
lpar_t state_query ;
lpar_t or_queryargs ;
lpar_t and_queryargs ;
lpar_t or_query ;
lpar_t and_query ;
and_queryargs = lpar_create_lst(LPAR_LST_QEXPR_ARGS) ;
or_queryargs = lpar_create_lst(LPAR_LST_QEXPR_ARGS) ;
/* create name simple query */
name_query = lpar_create_lst(LPAR_LST_SIMPLEQUERY) ;
lpar_append_lst(name_query, lpar_create_blk(LPAR_BLK_SEARCHQUERY,
name_value,
strlen(name_value))) ;
lpar_append_lst(name_query,
lpar_create_strarr(LPAR_STRARR_FIELDNAMES, name_fields, 3)) ;
/* assign name to this querylet */
lpar_append_lst(name_query, lpar_create_str(LPAR_STR_QLETNAME, "primary")) ;
/* add to Or query args. */
lpar_append_lst(or_queryargs, name_query) ;
/* create first aka simple query */
name_query = lpar_create_lst(LPAR_LST_SIMPLEQUERY) ;
lpar_append_lst(name_query, lpar_create_blk(LPAR_BLK_SEARCHQUERY,
name_value,
strlen(name_value))) ;
lpar_append_lst(name_query,
lpar_create_strarr(LPAR_STRARR_FIELDNAMES, aka1_fields, 1)) ;
/* assign name to this querylet */
lpar_append_lst(name_query, lpar_create_str(LPAR_STR_QLETNAME, "aka1")) ;
/* add to Or query args. */
lpar_append_lst(or_queryargs, name_query) ;
/* create second aka simple query */
name_query = lpar_create_lst(LPAR_LST_SIMPLEQUERY) ;
lpar_append_lst(name_query, lpar_create_blk(LPAR_BLK_SEARCHQUERY,
name_value,
strlen(name_value))) ;
lpar_append_lst(name_query,
lpar_create_strarr(LPAR_STRARR_FIELDNAMES, aka2_fields, 1)) ;
/* assign name to this querylet */
lpar_append_lst(name_query, lpar_create_str(LPAR_STR_QLETNAME, "aka2")) ;
/* add to Or query args. */
lpar_append_lst(or_queryargs, name_query) ;
/* create OR query */
or_query = lpar_create_lst(LPAR_LST_QEXPR) ;
lpar_append_lst(or_query,
lpar_create_int(LPAR_INT_QEXPR_TYPE, LKT_QEXPR_OR)) ;
/* add to And query arguments. */
lpar_append_lst(and_queryargs, or_query) ;
/* create simple queries for other items */
street_query = lpar_create_lst(LPAR_LST_SIMPLEQUERY) ;
lpar_append_lst(street_query, lpar_create_blk(LPAR_BLK_SEARCHQUERY,
street_value,
strlen(street_value))) ;
lpar_append_lst(street_query,
lpar_create_strarr(LPAR_STRARR_FIELDNAMES, street_fields, 1)) ;
/* add to And query args. */
lpar_append_lst(and_queryargs, street_query) ;
city_query = lpar_create_lst(LPAR_LST_SIMPLEQUERY) ;
lpar_append_lst(city_query, lpar_create_blk(LPAR_BLK_SEARCHQUERY,
city_value,
strlen(city_value))) ;
lpar_append_lst(city_query,
lpar_create_strarr(LPAR_STRARR_FIELDNAMES, city_fields, 1)) ;
/* add to And query args. */
lpar_append_lst(and_queryargs, city_query) ;
state_query = lpar_create_lst(LPAR_LST_SIMPLEQUERY) ;
lpar_append_lst(state_query, lpar_create_blk(LPAR_BLK_SEARCHQUERY,
state_value,
strlen(state_value))) ;
lpar_append_lst(state_query,
lpar_create_strarr(LPAR_STRARR_FIELDNAMES, state_fields, 1)) ;
/* add to And query args. */
lpar_append_lst(and_queryargs, state_query) ;

 

When named querylets are included in a query, the returned stats list contains an LPAR_STRARR_QLETNAMES value. This lists the names of all of the named querylets. Each minfo record contains an LPAR_DBLARR_NAMEDQLETSCORES value. This contains the score for each of the named querylets. The scores are presented in the same order as the names in the LPAR_STRARR_QLETNAMES lpar. The following example shows how the match score for the primary set of names can be retrieved:

 

lpar_t        named_qlet_fields ;
unsigned char **qlet_names ;
int num_named_qlets ;
int qlet_idx ;
lpar_t *minfo_items ;
int numrecs ;
int recnum ;
lpar_t named_qlet_scores_lpar ;
double *named_qlet_scores ;
int num_named_qlet_scores ;
/* Get our list of named querylets. */
named_qlet_fields = lpar_find_lst_lpar(stats, LPAR_STRARR_QLETNAMES) ;
if (named_qlet_fields == LPAR_NULL) {
/* Handle Error. */
/* abort processing */
}
qlet_names = lpar_get_strarr(named_qlet_fields, &num_named_qlets) ;
/* find the position of the querylet named "primary". */
for (qlet_idx = 0 ;
( (qlet_idx < num_named_qlets)
&& (strcmp("primary",qlet_names[qlet_idx]) != 0)) ;
qlet_idx++ ) {
}
if (qlet_idx >= num_named_qlets) {
/* It is an unexpected error if it is not in the list. */
/* abort processing */
}
/* now scan all the minfo records, displaying the primary querylet score */
minfo_items = lpar_get_lst_item_array(minfo, &numrecs) ;
for (recnum = 0; recnum < numrecs; recnum++) {
/* find the named querylet scores for this record */
named_qlet_scores_lpar = lpar_find_lst_lpar(minfo_items[recnum],
LPAR_DBLARR_NAMEDQLETSCORES) ;
if (named_qlet_scores_lpar == LPAR_NULL) {
/* It is an unexpected error if this is not in the list. */
/* abort processing. */
}
named_qlet_scores = lpar_get_dblarr(named_qlet_scores_lpar,
num_named_qlet_scores) ;
if (num_named_qlet_scores != num_named_qlets) {
/* these lists are always the same length, so this is an error! */
/* abort processing */
}
/* display the score of the named querylet named "primary" */
printf("Primary score for record %d = %f\n",
recnum, named_qlet_scores[qlet_idx]) ;
}

 

The following are some points to remember about named querylets:

Querylet names are letter case sensitive. "Name" is different than "name".
Although the order of querylet names within LPAR_STRARR_QLETNAMES and scores within LPAR_DBLARR_NAMEDQLETSCORES are guaranteed to be the same, there is no guaranteed ordering of querylet names within LPAR_STRARR_QLETNAMES relative to the placement of the associated querylet in the query structure. In other words, you cannot infer the location of a named querylet score based on the position of the querylet in the query. You must use the LPAR_STRARR_QLETNAMES array to find the location.
A querylet name can be assigned to any type of querylet. All score generators and score combiner query types can be assigned a name.
Note: All querylet names must be unique. The same name cannot be assigned to different querylets.