/// <summary>
        /// Performs a substring sequence query on <see cref="Trinity.Global.LocalStorage"/>. The semantics of
        /// this type of query is that, given a sequence of query strings <c>q_1, q_2,...,q_n</c> in
        /// <paramref name="query"/>, the match condition on a target string is that all the strings in the sequence
        /// are the substrings of the target string, and the order of the substring occurrences should correspond
        /// strictly to that given by <paramref name="query"/>. For example (let <c>S</c> denote the target string):
        /// <example>
        /// <list type="bullet">
        /// <item>
        /// <c>S=..q1....q2..q3{and so on}...qn...</c> is a match.
        /// </item>
        /// <item>
        /// <c>S=.....q1q2..q4{and there are missing substrings in the sequence}...qn...</c> is not match.
        /// </item>
        /// <item>
        /// <c>S=..q5..q3.q1{all the substrings in the sequence are present, but never in the corresponding order}...qn...</c> is not match.
        /// </item>
        /// </list>
        /// </example>
        /// The target field to query on is specified with <paramref name="query"/>, <seealso cref="t_Namespace.IndexIdentifier"/>.
        /// </summary>
        /// <param name="index_id">The identifier of the field that the query should be performed on.</param>
        /// <param name="query">The sequence of query strings.</param>
        /// <returns>
        /// A list of cell ids, of which the given query string sequence is matched on the target field, or
        /// an element it if it is a container of strings.
        /// </returns>
        public static List <long> SubstringQuery(IndexIdentifier index_id, params string[] query)
        {
            switch (index_id.id)
            {
            /*FOREACH*/
            /*IF("$t_index->type == IT_SUBSTRING")*/
            case t_index_id:
            {
                return(t_index_name_SubstringQuery(query));
            }

            /*END*/
            /*END*/
            default:
                throw new Exception("The target field does not have a substring index.");
            }
        }
Exemple #2
0
        /// <summary>
        /// Updates the index on the given field.
        /// </summary>
        /// <param name="index_id">The identifier of the field whose index should be rebuilt.</param>
        public static void UpdateSubstringQueryIndex(IndexIdentifier index_id)
        {
            switch (index_id.id)
            {
            /*FOREACH*/
            /*IF("$t_index->type == IT_SUBSTRING")*/
            case t_index_id:
            {
                Log.WriteLine(LogLevel.Info, "Index: updating substring index of t_index_name");
                System.Diagnostics.Stopwatch sw = System.Diagnostics.Stopwatch.StartNew();

                InvertedBigramIndexer  new_index;
                InvertedBigramSearcher new_searcher;
                ulong old_version = t_index_name_substring_index_version;

                /**
                 *  Lock the original index to prevent multiple updates
                 *  to be executed simultaneously.
                 */

                lock (t_index_name_substring_index_lock)
                {
                    /*
                     * If the index version has changed, it means that someone else
                     * has updated the index while we're blocked on the old index object.
                     */
                    if (t_index_name_substring_index_version != old_version)
                    {
                        Log.WriteLine(LogLevel.Info, "Index: Substring index of t_index_name is already updated, stopping current action.");
                        break;
                    }

                    new_index = new InvertedBigramIndexer("t_index_name");
                    foreach (var accessor in Global.LocalStorage.t_cell_name_Accessor_Selector())
                    {
                        bool optional_not_exist = true;
                        META_VAR("auto", "access_chain", "$t_index->resolve_target()");
                        META_VAR("std::string", "field_name");
                        META_VAR("bool", "has_optional", "false");
                        META("for(auto *field : *%access_chain){");
                        MAP_VAR("t_field_name", "%field_name + \"Contains_\" + *field->name");
                        IF("field->is_optional()");
                        META("%has_optional = true;");
                        if (accessor.t_field_name)
                        {
                            END();
                        }
                        META("%field_name.append(*field->name).append(\".\");}");
                        IF("%has_optional");
                        {
                            optional_not_exist = false;
                        }
                        if (optional_not_exist)
                        {
                            break;
                        }
                        END();
                        IF("$t_index->target_field->fieldType->is_string()");
                        {
                            MAP_VAR("t_field_name", "target", MemberOf = "t_index");
                            new_index.AddItem(accessor.t_field_name, accessor.CellId);
                        }
                        ELSE();
                        {
                            META_VAR("std::vector<NFieldType*>*", "container_chain");
                            META("%container_chain = $t_index->target_field->fieldType->resolve_container_chain();");
                            META("%container_chain->pop_back();");
                            MAP_LIST("t_container_chain", "%container_chain");

                            META_VAR("std::string", "field_name");
                            META("%field_name = \"accessor.\" + *$t_index->target;");
                            MAP_VAR("t_field_name", "%field_name");

                            MAP_VAR("t_element", "std::string(\"element_\") + GetString(GET_ITERATOR_VALUE())");
                            META_VAR("int", "final_element", "-1");
                            FOREACH(); USE_LIST("t_container_chain");
                            foreach (var t_element in t_field_name)
                            /*META("%field_name = $t_element; ++%final_element;")*/
                            /*END*/
                            {
                                MAP_VAR("t_element", "std::string(\"element_\") + GetString(%final_element)");
                                new_index.AddItem((string)t_element, accessor.CellId);
                            }

                            META("delete %container_chain;");
                        }
                        END();
                    }
                    new_index.BuildIndex();
                    new_searcher = new InvertedBigramSearcher(true, "t_index_name");

                    ++t_index_name_substring_index_version;
                }
                /*  Update the index objects now.  */
                lock (s_IndexLock)
                {
                    t_index_name_substring_index    = new_index;
                    t_index_name_substring_searcher = new_searcher;
                }

                sw.Stop();
                Log.WriteLine(LogLevel.Info, "Index: Finished updating the substring index of t_index_name. Time = {0}ms.", sw.ElapsedMilliseconds);
                break;
            }

            /*END*/
            /*END*/
            default:
                throw new Exception("The target field does not have a substring index.");
            }
        }