[Groonga-commit] groonga/groonga [master] Implemented black list for suggest.

Back to archive index

null+****@clear***** null+****@clear*****
2011年 3月 3日 (木) 14:45:20 JST


Tasuku SUENAGA a.k.a. gunyarakun	2011-03-03 05:45:20 +0000 (Thu, 03 Mar 2011)

  New Revision: 860ec69f9e56b58afda8375c453cfbdff7bab3dd

  Log:
    Implemented black list for suggest.

  Modified files:
    plugins/suggest/suggest.c
    src/suggest/groonga_suggest_ddl.txt

  Modified: plugins/suggest/suggest.c (+76 -57)
===================================================================
--- plugins/suggest/suggest.c    2011-02-28 03:02:49 +0000 (1c7c00e)
+++ plugins/suggest/suggest.c    2011-03-03 05:45:20 +0000 (1db5a3e)
@@ -57,14 +57,14 @@ grn_parse_suggest_types(const char *nptr, const char *end)
 }
 
 static int32_t
-cooccur_search(grn_ctx *ctx, grn_obj *table, grn_id id, grn_obj *res, int query_type)
+cooccur_search(grn_ctx *ctx, grn_obj *items, grn_obj *items_boost, grn_id id, grn_obj *res, int query_type)
 {
   int32_t max_score = 0;
   if (id) {
     grn_ii_cursor *c;
-    grn_obj *co = grn_obj_column(ctx, table, CONST_STR_LEN("co"));
+    grn_obj *co = grn_obj_column(ctx, items, CONST_STR_LEN("co"));
     grn_obj *pairs = grn_ctx_at(ctx, grn_obj_get_range(ctx, co));
-    grn_obj *items_freq = grn_obj_column(ctx, table, CONST_STR_LEN("freq"));
+    grn_obj *items_freq = grn_obj_column(ctx, items, CONST_STR_LEN("freq"));
     grn_obj *pairs_freq, *pairs_post = grn_obj_column(ctx, pairs, CONST_STR_LEN("post"));
     switch (query_type) {
     case COMPLETE :
@@ -82,23 +82,27 @@ cooccur_search(grn_ctx *ctx, grn_obj *table, grn_id id, grn_obj *res, int query_
     if ((c = grn_ii_cursor_open(ctx, (grn_ii *)co, id, GRN_ID_NIL, GRN_ID_MAX,
                                 ((grn_ii *)co)->n_elements - 1, 0))) {
       grn_ii_posting *p;
-      grn_obj post, pair_freq, item_freq;
-      GRN_RECORD_INIT(&post, 0, grn_obj_id(ctx, table));
+      grn_obj post, pair_freq, item_freq, item_boost;
+      GRN_RECORD_INIT(&post, 0, grn_obj_id(ctx, items));
       GRN_INT32_INIT(&pair_freq, 0);
       GRN_INT32_INIT(&item_freq, 0);
+      GRN_INT32_INIT(&item_boost, 0);
       while ((p = grn_ii_cursor_next(ctx, c))) {
         grn_id post_id;
-        int pfreq, ifreq;
+        int pfreq, ifreq, boost;
         GRN_BULK_REWIND(&post);
         GRN_BULK_REWIND(&pair_freq);
         GRN_BULK_REWIND(&item_freq);
+        GRN_BULK_REWIND(&item_boost);
         grn_obj_get_value(ctx, pairs_post, p->rid, &post);
         grn_obj_get_value(ctx, pairs_freq, p->rid, &pair_freq);
         post_id = GRN_RECORD_VALUE(&post);
         grn_obj_get_value(ctx, items_freq, post_id, &item_freq);
+        grn_obj_get_value(ctx, items_boost, post_id, &item_boost);
         pfreq = GRN_INT32_VALUE(&pair_freq);
         ifreq = GRN_INT32_VALUE(&item_freq);
-        if (pfreq && ifreq) {
+        boost = GRN_INT32_VALUE(&item_boost);
+        if (pfreq && ifreq && boost >= 0) {
           grn_rset_recinfo *ri;
           void *value;
           int32_t score = pfreq;
@@ -114,6 +118,7 @@ cooccur_search(grn_ctx *ctx, grn_obj *table, grn_id id, grn_obj *res, int query_
       GRN_OBJ_FIN(ctx, &post);
       GRN_OBJ_FIN(ctx, &pair_freq);
       GRN_OBJ_FIN(ctx, &item_freq);
+      GRN_OBJ_FIN(ctx, &item_boost);
       grn_ii_cursor_close(ctx, c);
     }
   }
@@ -164,18 +169,18 @@ output(grn_ctx *ctx, grn_obj *table, grn_obj *res, grn_id tid,
 }
 
 static void
-complete(grn_ctx *ctx, grn_obj *table, grn_obj *col, grn_obj *query, grn_obj *sortby,
+complete(grn_ctx *ctx, grn_obj *items, grn_obj *items_boost, grn_obj *col,
+         grn_obj *query, grn_obj *sortby,
          grn_obj *output_columns, int offset, int limit)
 {
   grn_obj *res;
-  grn_obj *items_freq = grn_obj_column(ctx, table, CONST_STR_LEN("freq"));
-  grn_obj *items_boost = grn_obj_column(ctx, table, CONST_STR_LEN("boost"));
+  grn_obj *items_freq = grn_obj_column(ctx, items, CONST_STR_LEN("freq"));
   grn_obj item_freq, item_boost;
   GRN_INT32_INIT(&item_freq, 0);
   GRN_INT32_INIT(&item_boost, 0);
   if ((res = grn_table_create(ctx, NULL, 0, NULL,
-                              GRN_TABLE_HASH_KEY|GRN_OBJ_WITH_SUBREC, table, NULL))) {
-    grn_id tid = grn_table_get(ctx, table, TEXT_VALUE_LEN(query));
+                              GRN_TABLE_HASH_KEY|GRN_OBJ_WITH_SUBREC, items, NULL))) {
+    grn_id tid = grn_table_get(ctx, items, TEXT_VALUE_LEN(query));
     if (GRN_TEXT_LEN(query)) {
       grn_str *norm;
       grn_table_cursor *cur;
@@ -194,18 +199,21 @@ complete(grn_ctx *ctx, grn_obj *table, grn_obj *col, grn_obj *query, grn_obj *so
                                              GRN_ID_NIL, GRN_ID_MAX, 1, 0))) {
                 grn_ii_posting *p;
                 while ((p = grn_ii_cursor_next(ctx, icur))) {
-                  int32_t score;
-                  grn_rset_recinfo *ri;
-                  void *value;
-                  grn_hash_add(ctx, (grn_hash *)res,
-                               &p->rid, sizeof(grn_id), &value, NULL);
-                  ri = value;
                   GRN_BULK_REWIND(&item_freq);
                   GRN_BULK_REWIND(&item_boost);
                   grn_obj_get_value(ctx, items_freq, p->rid, &item_freq);
                   grn_obj_get_value(ctx, items_boost, p->rid, &item_boost);
-                  score = GRN_INT32_VALUE(&item_freq) + GRN_INT32_VALUE(&item_boost);
-                  ri->score += score;
+                  if (GRN_INT32_VALUE(&item_boost) >= 0) {
+                    void *value;
+                    int32_t score;
+                    grn_rset_recinfo *ri;
+                    score = GRN_INT32_VALUE(&item_freq) +
+                            GRN_INT32_VALUE(&item_boost);
+                    grn_hash_add(ctx, (grn_hash *)res,
+                                 &p->rid, sizeof(grn_id), &value, NULL);
+                    ri = value;
+                    ri->score += score;
+                  }
                 }
                 grn_ii_cursor_close(ctx, icur);
               }
@@ -219,28 +227,32 @@ complete(grn_ctx *ctx, grn_obj *table, grn_obj *col, grn_obj *query, grn_obj *so
         }
         grn_str_close(ctx, norm);
       }
-      cooccur_search(ctx, table, tid, res, COMPLETE);
+      cooccur_search(ctx, items, items_boost, tid, res, COMPLETE);
       if (!grn_table_size(ctx, res) &&
-          (cur = grn_table_cursor_open(ctx, table, TEXT_VALUE_LEN(query),
+          (cur = grn_table_cursor_open(ctx, items, TEXT_VALUE_LEN(query),
                                        NULL, 0, 0, -1, GRN_CURSOR_PREFIX))) {
         grn_id id;
         while ((id = grn_table_cursor_next(ctx, cur))) {
-          int32_t score;
-          grn_rset_recinfo *ri;
-          void *value;
-          grn_hash_add(ctx, (grn_hash *)res, &id, sizeof(grn_id), &value, NULL);
-          ri = value;
           GRN_BULK_REWIND(&item_freq);
           GRN_BULK_REWIND(&item_boost);
           grn_obj_get_value(ctx, items_freq, id, &item_freq);
           grn_obj_get_value(ctx, items_boost, id, &item_boost);
-          score = GRN_INT32_VALUE(&item_freq) + GRN_INT32_VALUE(&item_boost);
-          ri->score += score;
+          if (GRN_INT32_VALUE(&item_boost) >= 0) {
+            void *value;
+            int32_t score;
+            grn_rset_recinfo *ri;
+            grn_hash_add(ctx, (grn_hash *)res, &id, sizeof(grn_id),
+                         &value, NULL);
+            score = GRN_INT32_VALUE(&item_freq) +
+                    GRN_INT32_VALUE(&item_boost);
+            ri = value;
+            ri->score += score;
+          }
         }
         grn_table_cursor_close(ctx, cur);
       }
     }
-    output(ctx, table, res, tid, sortby, output_columns, offset, limit);
+    output(ctx, items, res, tid, sortby, output_columns, offset, limit);
     grn_obj_close(ctx, res);
   } else {
     ERR(GRN_UNKNOWN_ERROR, "cannot create temporary table.");
@@ -250,23 +262,23 @@ complete(grn_ctx *ctx, grn_obj *table, grn_obj *col, grn_obj *query, grn_obj *so
 }
 
 static void
-correct(grn_ctx *ctx, grn_obj *table, grn_obj *query, grn_obj *sortby,
+correct(grn_ctx *ctx, grn_obj *items, grn_obj *items_boost,
+        grn_obj *query, grn_obj *sortby,
         grn_obj *output_columns, int offset, int limit)
 {
   grn_obj *res;
-  grn_obj *items_freq2 = grn_obj_column(ctx, table, CONST_STR_LEN("freq2"));
-  grn_obj *items_boost = grn_obj_column(ctx, table, CONST_STR_LEN("boost"));
+  grn_obj *items_freq2 = grn_obj_column(ctx, items, CONST_STR_LEN("freq2"));
   grn_obj item_freq2, item_boost;
   GRN_INT32_INIT(&item_freq2, 0);
   GRN_INT32_INIT(&item_boost, 0);
   if ((res = grn_table_create(ctx, NULL, 0, NULL,
-                              GRN_TABLE_HASH_KEY|GRN_OBJ_WITH_SUBREC, table, NULL))) {
-    grn_id tid = grn_table_get(ctx, table, TEXT_VALUE_LEN(query));
-    int32_t max_score = cooccur_search(ctx, table, tid, res, CORRECT);
+                              GRN_TABLE_HASH_KEY|GRN_OBJ_WITH_SUBREC, items, NULL))) {
+    grn_id tid = grn_table_get(ctx, items, TEXT_VALUE_LEN(query));
+    int32_t max_score = cooccur_search(ctx, items, items_boost, tid, res, CORRECT);
     LAP(":", "cooccur(%d)", max_score);
     if (GRN_TEXT_LEN(query) && max_score < 100) {
       grn_obj *key, *index;
-      if ((key = grn_obj_column(ctx, table, CONST_STR_LEN("_key")))) {
+      if ((key = grn_obj_column(ctx, items, CONST_STR_LEN("_key")))) {
         if (grn_column_index(ctx, key, GRN_OP_MATCH, &index, 1, NULL)) {
           grn_select_optarg optarg;
           memset(&optarg, 0, sizeof(grn_select_optarg));
@@ -280,21 +292,26 @@ correct(grn_ctx *ctx, grn_obj *table, grn_obj *query, grn_obj *sortby,
             grn_hash_cursor *hc = grn_hash_cursor_open(ctx, (grn_hash *)res, NULL,
                                                        0, NULL, 0, 0, -1, 0);
             if (hc) {
-              int32_t score;
-              grn_id *rp;
-              grn_rset_recinfo *ri;
-              void *key, *value;
               while (grn_hash_cursor_next(ctx, hc)) {
+                void *key, *value;
                 if (grn_hash_cursor_get_key_value(ctx, hc, &key, NULL, &value)) {
+                  grn_id *rp;
                   rp = key;
-                  ri = value;
                   GRN_BULK_REWIND(&item_freq2);
                   GRN_BULK_REWIND(&item_boost);
                   grn_obj_get_value(ctx, items_freq2, *rp, &item_freq2);
                   grn_obj_get_value(ctx, items_boost, *rp, &item_boost);
-                  score = (GRN_INT32_VALUE(&item_freq2) >> 4) + GRN_INT32_VALUE(&item_boost);
-                  ri->score += score;
-                  if (score < 100) { grn_hash_cursor_delete(ctx, hc, NULL); }
+                  if (GRN_INT32_VALUE(&item_boost) >= 0) {
+                    int32_t score;
+                    grn_rset_recinfo *ri;
+                    score = (GRN_INT32_VALUE(&item_freq2) >> 4) +
+                            GRN_INT32_VALUE(&item_boost);
+                    ri = value;
+                    ri->score += score;
+                    if (score >= 100) { continue; }
+                  }
+                  /* score < 100 || item_boost < 0 */
+                  grn_hash_cursor_delete(ctx, hc, NULL);
                 }
               }
               grn_hash_cursor_close(ctx, hc);
@@ -342,7 +359,7 @@ correct(grn_ctx *ctx, grn_obj *table, grn_obj *query, grn_obj *sortby,
         grn_obj_unlink(ctx, key);
       }
     }
-    output(ctx, table, res, tid, sortby, output_columns, offset, limit);
+    output(ctx, items, res, tid, sortby, output_columns, offset, limit);
     grn_obj_close(ctx, res);
   } else {
     ERR(GRN_UNKNOWN_ERROR, "cannot create temporary table.");
@@ -352,15 +369,16 @@ correct(grn_ctx *ctx, grn_obj *table, grn_obj *query, grn_obj *sortby,
 }
 
 static void
-suggest(grn_ctx *ctx, grn_obj *table, grn_obj *query, grn_obj *sortby,
+suggest(grn_ctx *ctx, grn_obj *items, grn_obj *items_boost,
+        grn_obj *query, grn_obj *sortby,
         grn_obj *output_columns, int offset, int limit)
 {
   grn_obj *res;
   if ((res = grn_table_create(ctx, NULL, 0, NULL,
-                              GRN_TABLE_HASH_KEY|GRN_OBJ_WITH_SUBREC, table, NULL))) {
-    grn_id tid = grn_table_get(ctx, table, TEXT_VALUE_LEN(query));
-    cooccur_search(ctx, table, tid, res, SUGGEST);
-    output(ctx, table, res, tid, sortby, output_columns, offset, limit);
+                              GRN_TABLE_HASH_KEY|GRN_OBJ_WITH_SUBREC, items, NULL))) {
+    grn_id tid = grn_table_get(ctx, items, TEXT_VALUE_LEN(query));
+    cooccur_search(ctx, items, items_boost, tid, res, SUGGEST);
+    output(ctx, items, res, tid, sortby, output_columns, offset, limit);
     grn_obj_close(ctx, res);
   } else {
     ERR(GRN_UNKNOWN_ERROR, "cannot create temporary table.");
@@ -370,7 +388,7 @@ suggest(grn_ctx *ctx, grn_obj *table, grn_obj *query, grn_obj *sortby,
 static grn_obj *
 command_suggest(grn_ctx *ctx, int nargs, grn_obj **args, grn_user_data *user_data)
 {
-  grn_obj *table, *col;
+  grn_obj *items, *col, *items_boost;
   int types = grn_parse_suggest_types(GRN_TEXT_VALUE(VAR(0)), GRN_BULK_CURR(VAR(0)));
   int offset = GRN_TEXT_LEN(VAR(6))
     ? grn_atoi(GRN_TEXT_VALUE(VAR(6)), GRN_BULK_CURR(VAR(6)), NULL)
@@ -378,23 +396,24 @@ command_suggest(grn_ctx *ctx, int nargs, grn_obj **args, grn_user_data *user_dat
   int limit = GRN_TEXT_LEN(VAR(7))
     ? grn_atoi(GRN_TEXT_VALUE(VAR(7)), GRN_BULK_CURR(VAR(7)), NULL)
     : DEFAULT_LIMIT;
-  if ((table = grn_ctx_get(ctx, TEXT_VALUE_LEN(VAR(1))))) {
+  if ((items = grn_ctx_get(ctx, TEXT_VALUE_LEN(VAR(1)))) &&
+      (items_boost = grn_obj_column(ctx, items, CONST_STR_LEN("boost")))) {
     GRN_OUTPUT_MAP_OPEN("RESULT_SET", -1);
     if (types & COMPLETE) {
-      if ((col = grn_obj_column(ctx, table, TEXT_VALUE_LEN(VAR(2))))) {
+      if ((col = grn_obj_column(ctx, items, TEXT_VALUE_LEN(VAR(2))))) {
         GRN_OUTPUT_CSTR("complete");
-        complete(ctx, table, col, VAR(3), VAR(4), VAR(5), offset, limit);
+        complete(ctx, items, items_boost, col, VAR(3), VAR(4), VAR(5), offset, limit);
       } else {
         ERR(GRN_INVALID_ARGUMENT, "invalid column.");
       }
     }
     if (types & CORRECT) {
       GRN_OUTPUT_CSTR("correct");
-      correct(ctx, table, VAR(3), VAR(4), VAR(5), offset, limit);
+      correct(ctx, items, items_boost, VAR(3), VAR(4), VAR(5), offset, limit);
     }
     if (types & SUGGEST) {
       GRN_OUTPUT_CSTR("suggest");
-      suggest(ctx, table, VAR(3), VAR(4), VAR(5), offset, limit);
+      suggest(ctx, items, items_boost, VAR(3), VAR(4), VAR(5), offset, limit);
     }
     GRN_OUTPUT_MAP_CLOSE();
   } else {

  Modified: src/suggest/groonga_suggest_ddl.txt (+1 -1)
===================================================================
--- src/suggest/groonga_suggest_ddl.txt    2011-02-28 03:02:49 +0000 (c2ed4d5)
+++ src/suggest/groonga_suggest_ddl.txt    2011-03-03 05:45:20 +0000 (f82763f)
@@ -24,7 +24,7 @@ item: suggest候補として提示する個々の文字列を格納するテー
  freq: ユーザクエリにおいて入力された回数を記録します。
  last: ユーザクエリに最後に入力された時刻を記録します。
  freq2: ユーザクエリにおいてサブミットされた回数を記録します。
- boost: 当該文字列の露出を制御します。正値を指定すれば露出が頻繁になり、負値を指定すれば抑制されます。
+ boost: 当該文字列の露出を制御します。正値を指定すれば露出が頻繁になり、-1を指定すれば、露出されません。
  buzz: 入力回数の差分を記録します。
  co: 共起する他の文字列を参照するための索引です。
 




Groonga-commit メーリングリストの案内
Back to archive index