Command search takes limit parameter
authorAdam Dickmeiss <adam@indexdata.dk>
Fri, 5 Aug 2011 14:03:18 +0000 (16:03 +0200)
committerAdam Dickmeiss <adam@indexdata.dk>
Fri, 5 Aug 2011 14:03:18 +0000 (16:03 +0200)
The limit parameter allows a search to be limited one or more
facets and the corresponding values. This is for server side
filtering.

src/Makefile.am
src/client.c
src/client.h
src/facet_limit.c [new file with mode: 0644]
src/facet_limit.h [new file with mode: 0644]
src/http_command.c
src/session.c
src/session.h

index baa7a0d..5d69f20 100644 (file)
@@ -21,6 +21,7 @@ libpazpar2_a_SOURCES = \
        connection.c connection.h \
        database.c database.h \
        eventl.c eventl.h \
+       facet_limit.c facet_limit.h \
        getaddrinfo.c \
        host.h \
        http.c http.h http_command.c \
index 0ea7512..8841c10 100644 (file)
@@ -945,8 +945,41 @@ static char *make_solrquery(struct client *cl)
     return r;
 }
 
+static void apply_limit(struct session_database *sdb,
+                        facet_limits_t facet_limits,
+                        WRBUF w)
+{
+    int i = 0;
+    const char *name;
+    const char *value;
+    for (i = 0; (name = facet_limits_get(facet_limits, i, &value)); i++)
+    {
+        struct setting *s = 0;
+        
+        for (s = sdb->settings[PZ_FACETMAP]; s; s = s->next)
+        {
+            const char *p = strchr(s->name + 3, ':');
+            if (p && !strcmp(p + 1, name) && s->value && s->value[0])
+            {
+                wrbuf_insert(w, 0, "@and ", 5);
+                wrbuf_puts(w, " @attr 1=");
+                yaz_encode_pqf_term(w, s->value, strlen(s->value));
+                wrbuf_puts(w, " ");
+                yaz_encode_pqf_term(w, value, strlen(value));
+                break;
+            }
+        }
+        if (!s)
+        {
+            yaz_log(YLOG_WARN, "facet %s used, but no facetmap defined",
+                    name);
+        }
+    }
+}
+                        
 // Parse the query given the settings specific to this client
-int client_parse_query(struct client *cl, const char *query)
+int client_parse_query(struct client *cl, const char *query,
+                       facet_limits_t facet_limits)
 {
     struct session *se = client_get_session(cl);
     struct session_database *sdb = client_get_database(cl);
@@ -996,6 +1029,8 @@ int client_parse_query(struct client *cl, const char *query)
         wrbuf_puts(se->wrbuf, " ");
     }
 
+    apply_limit(sdb, facet_limits, se->wrbuf);
+
     if (!pqf_strftime || !*pqf_strftime)
         ccl_pquery(se->wrbuf, cn);
     else
index 52c8691..fcb4c9c 100644 (file)
@@ -24,6 +24,8 @@ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
 #ifndef CLIENT_H
 #define CLIENT_H
 
+#include "facet_limit.h"
+
 struct client;
 struct connection;
 
@@ -80,7 +82,8 @@ int client_is_active(struct client *cl);
 int client_is_active_preferred(struct client *cl);
 struct client *client_next_in_session(struct client *cl);
 
-int client_parse_query(struct client *cl, const char *query);
+int client_parse_query(struct client *cl, const char *query,
+                       facet_limits_t facet_limits);
 Odr_int client_get_hits(struct client *cl);
 int client_get_num_records(struct client *cl);
 int client_get_diagnostic(struct client *cl);
diff --git a/src/facet_limit.c b/src/facet_limit.c
new file mode 100644 (file)
index 0000000..dca5c29
--- /dev/null
@@ -0,0 +1,94 @@
+/* This file is part of Pazpar2.
+   Copyright (C) 2006-2011 Index Data
+
+Pazpar2 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, or (at your option) any later
+version.
+
+Pazpar2 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, write to the Free Software
+Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+
+*/
+
+/** \file facet_limit.c
+    \brief Parse facet limit
+*/
+
+#if HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include <string.h>
+#include <assert.h>
+
+#include <yaz/yaz-version.h>
+#include <yaz/nmem.h>
+
+#include "facet_limit.h"
+
+struct facet_limits {
+    NMEM nmem;
+    int num;
+    char **darray;
+};
+
+facet_limits_t facet_limits_create(const char *param)
+{
+    int i;
+    NMEM nmem = nmem_create();
+    facet_limits_t fl = nmem_malloc(nmem, sizeof(*fl));
+    fl->nmem = nmem;
+    fl->num = 0;
+    fl->darray = 0;
+    if (param)
+        nmem_strsplit_escape(fl->nmem, ",", param, &fl->darray,
+                             &fl->num, 1, '\\');
+    /* replace = with \0 .. for each item */
+    for (i = 0; i < fl->num; i++)
+    {
+        char *cp = strchr(fl->darray[i], '=');
+        if (!cp)
+        {
+            facet_limits_destroy(fl);
+            return 0;
+        }
+        *cp = '\0';
+    }
+    return fl;
+}
+
+int facet_limits_num(facet_limits_t fl)
+{
+    return fl->num;
+}
+
+const char *facet_limits_get(facet_limits_t fl, int idx, const char **value)
+{
+    if (idx >= fl->num || idx < 0)
+        return 0;
+    *value = fl->darray[idx] + strlen(fl->darray[idx]) + 1;
+    return fl->darray[idx];
+}
+
+void facet_limits_destroy(facet_limits_t fl)
+{
+    if (fl)
+        nmem_destroy(fl->nmem);
+}
+
+/*
+ * Local variables:
+ * c-basic-offset: 4
+ * c-file-style: "Stroustrup"
+ * indent-tabs-mode: nil
+ * End:
+ * vim: shiftwidth=4 tabstop=8 expandtab
+ */
+
diff --git a/src/facet_limit.h b/src/facet_limit.h
new file mode 100644 (file)
index 0000000..60b8e9a
--- /dev/null
@@ -0,0 +1,45 @@
+/* This file is part of Pazpar2.
+   Copyright (C) 2006-2011 Index Data
+
+Pazpar2 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, or (at your option) any later
+version.
+
+Pazpar2 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, write to the Free Software
+Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+
+*/
+
+#ifndef FACET_LIMIT_H
+#define FACET_LIMIT_H
+
+#include <yaz/yaz-util.h>
+
+typedef struct facet_limits *facet_limits_t;
+
+facet_limits_t facet_limits_create(const char *param);
+
+int facet_limits_num(facet_limits_t fl);
+
+const char *facet_limits_get(facet_limits_t fl, int idx, const char **value);
+
+void facet_limits_destroy(facet_limits_t fl);
+
+#endif
+
+/*
+ * Local variables:
+ * c-basic-offset: 4
+ * c-file-style: "Stroustrup"
+ * indent-tabs-mode: nil
+ * End:
+ * vim: shiftwidth=4 tabstop=8 expandtab
+ */
+
index 436d4e1..4258b29 100644 (file)
@@ -1117,6 +1117,7 @@ static void cmd_search(struct http_channel *c)
     const char *filter = http_argbyname(rq, "filter");
     const char *maxrecs = http_argbyname(rq, "maxrecs");
     const char *startrecs = http_argbyname(rq, "startrecs");
+    const char *limit = http_argbyname(rq, "limit");
     enum pazpar2_error_code code;
     const char *addinfo = 0;
 
@@ -1134,7 +1135,8 @@ static void cmd_search(struct http_channel *c)
         release_session(c, s);
         return;
     }
-    code = search(s->psession, query, startrecs, maxrecs, filter, &addinfo);
+    code = search(s->psession, query, startrecs, maxrecs, filter, limit,
+                  &addinfo);
     if (code)
     {
         error(rs, code, addinfo);
index 6002a80..622d6d6 100644 (file)
@@ -594,6 +594,7 @@ enum pazpar2_error_code search(struct session *se,
                                const char *query,
                                const char *startrecs, const char *maxrecs,
                                const char *filter,
+                               const char *limit,
                                const char **addinfo)
 {
     int live_channels = 0;
@@ -601,6 +602,7 @@ enum pazpar2_error_code search(struct session *se,
     int no_failed = 0;
     struct client_list *l;
     struct timeval tval;
+    facet_limits_t facet_limits;
 
     session_log(se, YLOG_DEBUG, "Search");
 
@@ -627,6 +629,12 @@ enum pazpar2_error_code search(struct session *se,
     
     tval.tv_sec += 5;
 
+    facet_limits = facet_limits_create(limit);
+    if (!facet_limits)
+    {
+        *addinfo = "limit";
+        return PAZPAR2_MALFORMED_PARAMETER_VALUE;
+    }
     for (l = se->clients; l; l = l->next)
     {
         struct client *cl = l->client;
@@ -637,7 +645,7 @@ enum pazpar2_error_code search(struct session *se,
             client_set_startrecs(cl, atoi(startrecs));
         if (prepare_session_database(se, client_get_database(cl)) < 0)
             ;
-        else if (client_parse_query(cl, query) < 0)
+        else if (client_parse_query(cl, query, facet_limits) < 0)
             no_failed++;
         else
         {
@@ -649,6 +657,7 @@ enum pazpar2_error_code search(struct session *se,
                 client_start_search(cl);
         }
     }
+    facet_limits_destroy(facet_limits);
     session_leave(se);
     if (no_working == 0)
     {
index 179ade2..ec699ee 100644 (file)
@@ -155,7 +155,8 @@ int load_targets(struct session *s, const char *fn);
 void statistics(struct session *s, struct statistics *stat);
 enum pazpar2_error_code search(struct session *s, const char *query,
                                const char *startrecs, const char *maxrecs,
-                               const char *filter, const char **addinfo);
+                               const char *filter, const char *limit,
+                               const char **addinfo);
 struct record_cluster **show_range_start(struct session *s,
                                          struct reclist_sortparms *sp,
                                          int start,