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: 共起する他の文字列を参照するための索引です。