Example #1
0
TopDocs*
PolySearcher_Top_Docs_IMP(PolySearcher *self, Query *query,
                          uint32_t num_wanted, SortSpec *sort_spec) {
    PolySearcherIVARS *const ivars = PolySearcher_IVARS(self);
    Schema   *schema      = PolySearcher_Get_Schema(self);
    VArray   *searchers   = ivars->searchers;
    I32Array *starts      = ivars->starts;
    HitQueue *hit_q       = sort_spec
                            ? HitQ_new(schema, sort_spec, num_wanted)
                            : HitQ_new(NULL, NULL, num_wanted);
    uint32_t  total_hits  = 0;
    Compiler *compiler    = Query_Is_A(query, COMPILER)
                            ? ((Compiler*)INCREF(query))
                            : Query_Make_Compiler(query, (Searcher*)self,
                                                  Query_Get_Boost(query),
                                                  false);

    for (uint32_t i = 0, max = VA_Get_Size(searchers); i < max; i++) {
        Searcher   *searcher   = (Searcher*)VA_Fetch(searchers, i);
        int32_t     base       = I32Arr_Get(starts, i);
        TopDocs    *top_docs   = Searcher_Top_Docs(searcher, (Query*)compiler,
                                                   num_wanted, sort_spec);
        VArray     *sub_match_docs = TopDocs_Get_Match_Docs(top_docs);

        total_hits += TopDocs_Get_Total_Hits(top_docs);

        S_modify_doc_ids(sub_match_docs, base);
        for (uint32_t j = 0, jmax = VA_Get_Size(sub_match_docs); j < jmax; j++) {
            MatchDoc *match_doc = (MatchDoc*)VA_Fetch(sub_match_docs, j);
            if (!HitQ_Insert(hit_q, INCREF(match_doc))) { break; }
        }

        DECREF(top_docs);
    }

    VArray  *match_docs = HitQ_Pop_All(hit_q);
    TopDocs *retval     = TopDocs_new(match_docs, total_hits);

    DECREF(match_docs);
    DECREF(compiler);
    DECREF(hit_q);
    return retval;
}
Example #2
0
SortCollector*
SortColl_init(SortCollector *self, Schema *schema, SortSpec *sort_spec,
              uint32_t wanted) {
    VArray *rules = sort_spec
                    ? (VArray*)INCREF(SortSpec_Get_Rules(sort_spec))
                    : S_default_sort_rules();
    uint32_t num_rules = VA_Get_Size(rules);

    // Validate.
    if (sort_spec && !schema) {
        THROW(ERR, "Can't supply a SortSpec without a Schema.");
    }
    if (!num_rules) {
        THROW(ERR, "Can't supply a SortSpec with no SortRules.");
    }

    // Init.
    Coll_init((Collector*)self);
    SortCollectorIVARS *const ivars = SortColl_IVARS(self);
    ivars->total_hits    = 0;
    ivars->bubble_doc    = INT32_MAX;
    ivars->bubble_score  = F32_NEGINF;
    ivars->seg_doc_max   = 0;

    // Assign.
    ivars->wanted        = wanted;

    // Derive.
    ivars->hit_q         = HitQ_new(schema, sort_spec, wanted);
    ivars->rules         = rules; // absorb refcount.
    ivars->num_rules     = num_rules;
    ivars->sort_caches   = (SortCache**)CALLOCATE(num_rules, sizeof(SortCache*));
    ivars->ord_arrays    = (void**)CALLOCATE(num_rules, sizeof(void*));
    ivars->actions       = (uint8_t*)CALLOCATE(num_rules, sizeof(uint8_t));

    // Build up an array of "actions" which we will execute during each call
    // to Collect(). Determine whether we need to track scores and field
    // values.
    ivars->need_score  = false;
    ivars->need_values = false;
    for (uint32_t i = 0; i < num_rules; i++) {
        SortRule *rule   = (SortRule*)VA_Fetch(rules, i);
        int32_t rule_type  = SortRule_Get_Type(rule);
        ivars->actions[i] = S_derive_action(rule, NULL);
        if (rule_type == SortRule_SCORE) {
            ivars->need_score = true;
        }
        else if (rule_type == SortRule_FIELD) {
            CharBuf *field = SortRule_Get_Field(rule);
            FieldType *type = Schema_Fetch_Type(schema, field);
            if (!type || !FType_Sortable(type)) {
                THROW(ERR, "'%o' isn't a sortable field", field);
            }
            ivars->need_values = true;
        }
    }

    // Perform an optimization.  So long as we always collect docs in
    // ascending order, Collect() will favor lower doc numbers -- so we may
    // not need to execute a final COMPARE_BY_DOC_ID action.
    ivars->num_actions = num_rules;
    if (ivars->actions[num_rules - 1] == COMPARE_BY_DOC_ID) {
        ivars->num_actions--;
    }

    // Override our derived actions with an action which will be excecuted
    // autmatically until the queue fills up.
    ivars->auto_actions    = (uint8_t*)MALLOCATE(1);
    ivars->auto_actions[0] = wanted ? AUTO_ACCEPT : AUTO_REJECT;
    ivars->derived_actions = ivars->actions;
    ivars->actions         = ivars->auto_actions;


    // Prepare a MatchDoc-in-waiting.
    VArray *values = ivars->need_values ? VA_new(num_rules) : NULL;
    float   score  = ivars->need_score  ? F32_NEGINF : F32_NAN;
    ivars->bumped = MatchDoc_new(INT32_MAX, score, values);
    DECREF(values);

    return self;
}