/// <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."); } }
/// <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."); } }