using System.ComponentModel; using System.Text.RegularExpressions; namespace OASystem.Infrastructure.Tools { /// /// 增强版高级搜索助手(支持智能拆分组合词) /// 支持组合查询:多词条/单词条 + 单字 混合搜索 /// 提供智能搜索条件构建、相关性分析、分阶段搜索等功能 /// public class AdvancedSearchHelper { #region 公共方法 - 主要搜索功能 /// /// 构建增强搜索条件(支持组合查询和智能拆分) /// /// 搜索关键词 /// 搜索字段列表 /// 参数前缀,用于避免参数名冲突 /// 搜索模式,默认为自动检测 /// 组合模式,默认智能混合 /// 搜索配置选项 /// 构建的SQL条件和参数 /// /// /// var fields = new List<string> { "Name", "Description" }; /// var config = new SearchConfig { /// EnableSmartSplitting = true, // 启用智能拆分 /// RequireAllWordsForSplit = false /// }; /// var (condition, parameters) = AdvancedSearchHelper.BuildEnhancedSearchCondition( /// "重庆科学", /// fields, /// "search_", /// SearchMode.AutoDetect, /// CombinationMode.SmartMix, /// config /// ); /// /// public static (string Condition, List Parameters) BuildEnhancedSearchCondition( string searchTerm, List searchFields, string prefix = "", SearchMode searchMode = SearchMode.AutoDetect, CombinationMode combinationMode = CombinationMode.SmartMix, SearchConfig config = null) { // 参数验证 if (searchFields == null || !searchFields.Any()) throw new ArgumentException("搜索字段列表不能为空", nameof(searchFields)); if (string.IsNullOrWhiteSpace(searchTerm)) return (string.Empty, new List()); searchTerm = searchTerm.Trim(); config ??= new SearchConfig(); // 检查搜索词长度 if (searchTerm.Length > config.MaxSearchTermLength) searchTerm = searchTerm.Substring(0, config.MaxSearchTermLength); // 分析搜索词结构 var structure = AnalyzeSearchStructure(searchTerm); // 根据组合模式构建条件 return combinationMode switch { CombinationMode.SmartMix => BuildSmartMixCondition(structure, searchFields, prefix, searchMode, config), CombinationMode.WordsAndChars => BuildWordsAndCharsCondition(structure, searchFields, prefix, config), CombinationMode.WordsOnly => BuildWordsOnlyCondition(structure, searchFields, prefix, config), CombinationMode.CharsOnly => BuildCharsOnlyCondition(structure, searchFields, prefix, config), _ => BuildSmartMixCondition(structure, searchFields, prefix, searchMode, config) }; } /// /// 为Sugar ORM构建增强搜索条件 /// public static (string Condition, List Parameters) BuildSugarSearchCondition( string searchTerm, List searchFields, string prefix = "", SearchMode searchMode = SearchMode.AutoDetect, CombinationMode combinationMode = CombinationMode.SmartMix, SearchConfig config = null) { // 先使用原有方法构建条件 var (condition, parameters) = BuildEnhancedSearchCondition( searchTerm, searchFields, prefix, searchMode, combinationMode, config); if (string.IsNullOrEmpty(condition)) return (string.Empty, parameters); // 转换参数名为Sugar ORM兼容格式 var sugarParameters = new List(); var paramMapping = new Dictionary(); int paramIndex = 0; foreach (var param in parameters) { var oldName = param.ParameterName; var newName = $"@{prefix}p{paramIndex++}"; paramMapping[oldName] = newName; sugarParameters.Add(new SugarParameter(newName, param.Value)); } // 替换参数名 foreach (var mapping in paramMapping) { condition = condition.Replace(mapping.Key, mapping.Value); } // 转换LIKE表达式为Sugar ORM格式 condition = Regex.Replace(condition, @"LIKE @\w+", match => { var paramName = match.Value.Substring(5); // 移除"LIKE " return $"LIKE '%' + {paramName} + '%'"; }); return (condition, sugarParameters); } /// /// 构建带相关性信息的搜索条件 /// /// 搜索关键词 /// 搜索字段列表 /// 参数前缀 /// 搜索模式 /// 搜索配置 /// 包含条件、参数和相关性的完整结果 public static (string Condition, List Parameters, RelevanceInfo Relevance) BuildRelevanceSearchCondition( string searchTerm, List searchFields, string prefix = "", SearchMode searchMode = SearchMode.AutoDetect, SearchConfig config = null) { config ??= new SearchConfig(); var structure = AnalyzeSearchStructure(searchTerm); var (condition, parameters) = BuildEnhancedSearchCondition( searchTerm, searchFields, prefix, searchMode, CombinationMode.SmartMix, config); var relevance = new RelevanceInfo { SearchStructure = structure, ExpectedMatches = CalculateExpectedMatches(structure, searchFields.Count), BoostFields = GetBoostFields(structure, searchFields), ScoringRules = GetScoringRules(structure, config), MatchStrategy = GetMatchStrategy(structure, config), GeneratedAt = DateTime.Now }; return (condition, parameters, relevance); } /// /// 构建分阶段搜索条件(用于分阶段匹配和降级搜索) /// /// 搜索关键词 /// 搜索字段列表 /// 参数前缀 /// 搜索配置 /// 按优先级排序的搜索阶段列表 public static List BuildStagedSearchConditions( string searchTerm, List searchFields, string prefix = "", SearchConfig config = null) { config ??= new SearchConfig(); var structure = AnalyzeSearchStructure(searchTerm); var stages = new List(); // 阶段1:精确匹配(完全相等) if (structure.Words.Any() && config.EnableExactMatch) { foreach (var word in structure.Words.Where(w => w.Length >= config.MinExactMatchLength)) { var (condition, parameters) = BuildExactCondition(word, searchFields, $"{prefix}exact_{stages.Count}"); if (!string.IsNullOrEmpty(condition)) { stages.Add(new SearchStage { Stage = 1, Name = $"精确匹配: {word}", Condition = condition, Parameters = parameters, Priority = 100, Description = $"完全匹配词语'{word}'", FallbackToNext = false }); } } } // 阶段2:开头匹配 if (structure.Words.Any() && config.EnablePrefixMatch) { foreach (var word in structure.Words) { var (condition, parameters) = BuildPrefixCondition(word, searchFields, $"{prefix}prefix_{stages.Count}"); if (!string.IsNullOrEmpty(condition)) { stages.Add(new SearchStage { Stage = 2, Name = $"开头匹配: {word}", Condition = condition, Parameters = parameters, Priority = 80, Description = $"以'{word}'开头", FallbackToNext = true }); } } } // 阶段3:词语模糊匹配 if (structure.Words.Any() && config.EnableFuzzySearch) { var wordsText = string.Join(" ", structure.Words); var (condition, parameters) = BuildMultiWordCondition( wordsText, searchFields, $"{prefix}fuzzy_{stages.Count}", config.RequireAllWords); if (!string.IsNullOrEmpty(condition)) { stages.Add(new SearchStage { Stage = 3, Name = "词语模糊匹配", Condition = condition, Parameters = parameters, Priority = 60, Description = $"包含词语: {wordsText}", FallbackToNext = true }); } } // 阶段4:单字匹配 if (structure.SingleChars.Any() && config.EnableCharSearch) { var charsText = string.Join("", structure.SingleChars); var (condition, parameters) = BuildSingleCharCondition( charsText, searchFields, $"{prefix}chars_{stages.Count}", config.RequireAllChars); if (!string.IsNullOrEmpty(condition)) { stages.Add(new SearchStage { Stage = 4, Name = "单字匹配", Condition = condition, Parameters = parameters, Priority = 40, Description = $"包含单字: {charsText}", FallbackToNext = true }); } } // 阶段5:智能拆分匹配(新增阶段) if (config.EnableSmartSplitting && structure.Words.Any(w => w.Length >= config.MinSplitLength)) { var longWords = structure.Words.Where(w => w.Length >= config.MinSplitLength).ToList(); foreach (var longWord in longWords) { if (IsSplittableCombinationWord(longWord)) { var (condition, parameters) = BuildSmartSplitConditionForWord( longWord, searchFields, $"{prefix}split_{stages.Count}", config); if (!string.IsNullOrEmpty(condition)) { stages.Add(new SearchStage { Stage = 5, Name = $"智能拆分: {longWord}", Condition = condition, Parameters = parameters, Priority = 50, // 优先级在词语模糊匹配和单字匹配之间 Description = $"智能拆分'{longWord}'为子词或单字", FallbackToNext = true }); } } } } // 阶段6:宽松混合匹配 if (stages.Any(s => s.Stage >= 3 && s.Stage <= 5)) { var mixedConditions = stages .Where(s => s.Stage >= 3 && s.Stage <= 5) .Select(s => s.Condition) .ToList(); var mixedParameters = stages .Where(s => s.Stage >= 3 && s.Stage <= 5) .SelectMany(s => s.Parameters) .ToList(); if (mixedConditions.Any()) { stages.Add(new SearchStage { Stage = 6, Name = "宽松混合匹配", Condition = $"({string.Join(" OR ", mixedConditions)})", Parameters = mixedParameters, Priority = 20, Description = "词语或单字的任意匹配", FallbackToNext = false }); } } return stages.OrderByDescending(s => s.Priority).ToList(); } #endregion #region 核心构建方法 /// /// 智能混合构建条件(支持智能拆分组合词) /// private static (string, List) BuildSmartMixCondition( SearchStructure structure, List searchFields, string prefix, SearchMode searchMode, SearchConfig config) { var parameters = new List(); var conditions = new List(); // 分析结构复杂度 var complexity = CalculateComplexityScore(structure); // 检查是否有需要智能拆分的组合词 var longWords = structure.Words.Where(w => w.Length >= config.MinSplitLength).ToList(); var shouldSplitLongWords = longWords.Any() && config.EnableSmartSplitting; if (shouldSplitLongWords && longWords.Any(w => IsSplittableCombinationWord(w))) { // 使用智能拆分策略处理组合词 return BuildSmartSplitCondition(structure, searchFields, prefix, config, longWords); } // 智能分析混合类型的特点 var hasLongWords = structure.Words.Any(w => w.Length >= 2); var hasManyChars = structure.SingleChars.Count >= 3; var isCharDominant = structure.SingleChars.Count > structure.Words.Count; var hasMixedTypes = structure.HasWords && structure.HasSingleChars; // 根据混合特点选择更精细的策略 string strategy; if (hasMixedTypes) { if (isCharDominant && hasManyChars) { strategy = "char_optimized"; // 单字主导,优化单字搜索 } else if (hasLongWords && !hasManyChars) { strategy = "word_focused"; // 词语为主,单字为辅 } else { strategy = complexity >= 6 ? "strict_mixed" : complexity >= 3 ? "balanced_mixed" : "loose_mixed"; } } else { strategy = complexity >= 7 ? "strict" : complexity >= 4 ? "balanced" : "loose"; } // 处理词语部分 if (structure.HasWords) { if (structure.Words.Count == 1) { // 单个词语 var (wordCondition, wordParams) = BuildSingleWordCondition( structure.Words[0], searchFields, $"{prefix}word", config); if (!string.IsNullOrEmpty(wordCondition)) { conditions.Add(wordCondition); parameters.AddRange(wordParams); } } else { // 多个词语 var wordsText = string.Join(" ", structure.Words); // 根据策略动态调整词语匹配要求 bool requireAllWords; if (strategy == "char_optimized" && isCharDominant) { // 单字主导时,放宽词语要求 requireAllWords = false; } else { requireAllWords = strategy.Contains("strict") || config.RequireAllWords; } var (wordsCondition, wordsParams) = BuildMultiWordCondition( wordsText, searchFields, $"{prefix}words", requireAllWords); if (!string.IsNullOrEmpty(wordsCondition)) { conditions.Add(wordsCondition); parameters.AddRange(wordsParams); } } } // 处理单字部分 - 优化策略 if (structure.HasSingleChars) { var charsText = string.Join("", structure.SingleChars); // 根据策略动态调整单字匹配要求 bool requireAllChars; string charStrategy; if (strategy == "char_optimized") { // 单字优化策略:多个单字时放宽要求 requireAllChars = structure.SingleChars.Count <= 3; // 3个及以下单字要求全部匹配 charStrategy = "optimized"; } else if (strategy.Contains("loose")) { requireAllChars = false; charStrategy = "loose"; } else if (strategy.Contains("strict")) { requireAllChars = true; charStrategy = "strict"; } else { requireAllChars = strategy.Contains("balanced") && structure.SingleChars.Count <= 2; charStrategy = "balanced"; } var (charsCondition, charsParams) = BuildEnhancedCharCondition( charsText, searchFields, $"{prefix}chars", requireAllChars, charStrategy); if (!string.IsNullOrEmpty(charsCondition)) { conditions.Add(charsCondition); parameters.AddRange(charsParams); } } // 构建最终条件 if (!conditions.Any()) return (string.Empty, parameters); string finalCondition = BuildMixedConditionByStrategy( conditions, structure, strategy); return (finalCondition, parameters); } /// /// 构建智能拆分条件(针对长词如"重庆科学") /// private static (string, List) BuildSmartSplitCondition( SearchStructure structure, List searchFields, string prefix, SearchConfig config, List longWords) { var parameters = new List(); var conditions = new List(); // 处理所有长词(需要拆分的词) foreach (var longWord in longWords) { if (IsSplittableCombinationWord(longWord)) { // 为每个长词构建多层次条件 var (wordConditions, wordParams) = BuildMultiLevelConditionForWord( longWord, searchFields, $"{prefix}word_{longWord.GetHashCode()}", config); conditions.AddRange(wordConditions); parameters.AddRange(wordParams); } else { // 普通长词,直接搜索 var (wordCondition, wordParams) = BuildSingleWordCondition( longWord, searchFields, $"{prefix}long_{parameters.Count}", config); if (!string.IsNullOrEmpty(wordCondition)) { conditions.Add(wordCondition); parameters.AddRange(wordParams); } } } // 处理剩余的非长词 var normalWords = structure.Words.Where(w => w.Length < config.MinSplitLength).ToList(); if (normalWords.Any()) { var wordsText = string.Join(" ", normalWords); var (normalCondition, normalParams) = BuildMultiWordCondition( wordsText, searchFields, $"{prefix}normal", config.RequireAllWords); if (!string.IsNullOrEmpty(normalCondition)) { conditions.Add(normalCondition); parameters.AddRange(normalParams); } } // 处理原有的单字 if (structure.SingleChars.Any()) { var charsText = string.Join("", structure.SingleChars); var (charCondition, charParams) = BuildSingleCharCondition( charsText, searchFields, $"{prefix}single", false); if (!string.IsNullOrEmpty(charCondition)) { conditions.Add(charCondition); parameters.AddRange(charParams); } } // 构建最终条件:使用层次化OR连接 if (conditions.Count == 0) return (string.Empty, parameters); if (conditions.Count == 1) return (conditions[0], parameters); // 对条件进行分组和优先级排序 var groupedConditions = GroupConditionsByPriority(conditions, longWords); return (BuildHierarchicalCondition(groupedConditions), parameters); } /// /// 为单个长词构建多层次条件 /// private static (List Conditions, List Parameters) BuildMultiLevelConditionForWord( string longWord, List searchFields, string prefix, SearchConfig config) { var conditions = new List(); var parameters = new List(); // 第一层:完整词匹配(最高优先级) var (fullCondition, fullParams) = BuildSingleWordCondition( longWord, searchFields, $"{prefix}_full", config); if (!string.IsNullOrEmpty(fullCondition)) { conditions.Add(fullCondition); parameters.AddRange(fullParams); } // 第二层:智能拆分成子词 var subWords = SplitCombinationWord(longWord); if (subWords.Count >= 2) { var (splitCondition, splitParams) = BuildMultiWordCondition( string.Join(" ", subWords), searchFields, $"{prefix}_split", config.RequireAllWordsForSplit); if (!string.IsNullOrEmpty(splitCondition)) { conditions.Add($"({splitCondition})"); // 用括号包裹 parameters.AddRange(splitParams); } } // 第三层:拆分成单字作为备选 var chars = longWord.ToCharArray().Select(c => c.ToString()).ToList(); var (charCondition, charParams) = BuildSingleCharCondition( string.Join("", chars), searchFields, $"{prefix}_chars", config.RequireAllCharsForSplit); if (!string.IsNullOrEmpty(charCondition)) { conditions.Add($"({charCondition})"); parameters.AddRange(charParams); } // 如果有多层条件,构建OR连接 if (conditions.Count > 1) { var combinedCondition = $"({string.Join(" OR ", conditions)})"; return (new List { combinedCondition }, parameters); } return (conditions, parameters); } /// /// 构建智能拆分条件(用于分阶段搜索) /// private static (string, List) BuildSmartSplitConditionForWord( string longWord, List searchFields, string prefix, SearchConfig config) { var (conditions, parameters) = BuildMultiLevelConditionForWord(longWord, searchFields, prefix, config); if (conditions.Any()) { return (conditions[0], parameters); } return (string.Empty, new List()); } /// /// 词语和单字组合条件 /// private static (string, List) BuildWordsAndCharsCondition( SearchStructure structure, List searchFields, string prefix, SearchConfig config) { var parameters = new List(); var conditions = new List(); // 词语部分(必须满足) if (structure.Words.Any()) { var wordsText = string.Join(" ", structure.Words); var (wordsCondition, wordsParams) = BuildMultiWordCondition( wordsText, searchFields, $"{prefix}w", true); if (!string.IsNullOrEmpty(wordsCondition)) { conditions.Add(wordsCondition); parameters.AddRange(wordsParams); } } // 单字部分(作为增强条件) if (structure.SingleChars.Any()) { var charsText = string.Join("", structure.SingleChars); var (charsCondition, charsParams) = BuildSingleCharCondition( charsText, searchFields, $"{prefix}c", false); if (!string.IsNullOrEmpty(charsCondition)) { // 单字作为加分项,用OR连接 conditions.Add($"({charsCondition})"); parameters.AddRange(charsParams); } } if (!conditions.Any()) return (string.Empty, parameters); // 构建条件:词语必须满足,单字作为增强 string finalCondition = conditions.Count > 1 ? $"({conditions[0]} AND ({string.Join(" OR ", conditions.Skip(1))}))" : conditions[0]; return (finalCondition, parameters); } /// /// 仅词语条件 /// private static (string, List) BuildWordsOnlyCondition( SearchStructure structure, List searchFields, string prefix, SearchConfig config) { if (!structure.Words.Any()) return (string.Empty, new List()); var wordsText = string.Join(" ", structure.Words); if (structure.Words.Count == 1) { return BuildSingleWordCondition(wordsText, searchFields, prefix, config); } else { return BuildMultiWordCondition(wordsText, searchFields, prefix, config.RequireAllWords); } } /// /// 仅单字条件 /// private static (string, List) BuildCharsOnlyCondition( SearchStructure structure, List searchFields, string prefix, SearchConfig config) { if (!structure.SingleChars.Any()) return (string.Empty, new List()); var charsText = string.Join("", structure.SingleChars); return BuildSingleCharCondition(charsText, searchFields, prefix, config.RequireAllChars); } #endregion #region 基础条件构建方法 /// /// 构建单词条查询条件 /// public static (string Condition, List Parameters) BuildSingleWordCondition( string searchTerm, List searchFields, string prefix, SearchConfig config = null) { config ??= new SearchConfig(); var parameters = new List(); var fieldConditions = new List(); var paramName = $"{prefix}word"; foreach (var field in searchFields) { fieldConditions.Add($"{field} LIKE @{paramName}"); } string condition = $"({string.Join(" OR ", fieldConditions)})"; parameters.Add(new SugarParameter($"@{paramName}", $"%{searchTerm}%")); return (condition, parameters); } /// /// 构建多词条查询条件 /// public static (string Condition, List Parameters) BuildMultiWordCondition( string searchTerm, List searchFields, string prefix, bool requireAll = true) { var parameters = new List(); var separators = new[] { ' ', ',', '、', ',', ';', ';' }; var words = searchTerm.Split(separators, StringSplitOptions.RemoveEmptyEntries) .Select(w => w.Trim()) .Where(w => !string.IsNullOrEmpty(w)) .Distinct() .ToList(); if (!words.Any()) return (string.Empty, parameters); var wordConditions = new List(); foreach (var word in words) { var fieldConditions = new List(); var paramName = $"{prefix}word_{parameters.Count}"; foreach (var field in searchFields) { fieldConditions.Add($"{field} LIKE @{paramName}"); } wordConditions.Add($"({string.Join(" OR ", fieldConditions)})"); parameters.Add(new SugarParameter($"@{paramName}", $"%{word}%")); } // 构建条件 string condition; if (requireAll && words.Count > 1) { condition = $"({string.Join(" AND ", wordConditions)})"; } else if (!requireAll && words.Count > 1) { condition = $"({string.Join(" OR ", wordConditions)})"; } else { condition = wordConditions.FirstOrDefault() ?? ""; } return (condition, parameters); } /// /// 构建单字查询条件 /// public static (string Condition, List Parameters) BuildSingleCharCondition( string searchTerm, List searchFields, string prefix, bool requireAll = true) { var parameters = new List(); var cleanTerm = RemoveSeparators(searchTerm); var chars = cleanTerm.ToCharArray().Distinct().ToArray(); if (chars.Length == 0) return (string.Empty, parameters); var charConditions = new List(); foreach (char c in chars) { var fieldConditions = new List(); var paramName = $"{prefix}char_{parameters.Count}"; foreach (var field in searchFields) { fieldConditions.Add($"{field} LIKE @{paramName}"); } charConditions.Add($"({string.Join(" OR ", fieldConditions)})"); parameters.Add(new SugarParameter($"@{paramName}", $"%{c}%")); } // 构建条件 string condition; if (requireAll && chars.Length > 1) { condition = $"({string.Join(" AND ", charConditions)})"; } else if (!requireAll && chars.Length > 1) { condition = $"({string.Join(" OR ", charConditions)})"; } else { condition = charConditions.FirstOrDefault() ?? ""; } return (condition, parameters); } /// /// 构建增强的单字搜索条件(支持不同策略) /// private static (string, List) BuildEnhancedCharCondition( string searchTerm, List searchFields, string prefix, bool requireAll, string strategy) { var parameters = new List(); var cleanTerm = RemoveSeparators(searchTerm); var chars = cleanTerm.ToCharArray().Distinct().ToArray(); if (chars.Length == 0) return (string.Empty, parameters); // 根据策略调整处理方式 var charConditions = new List(); foreach (char c in chars) { var fieldConditions = new List(); var paramName = $"{prefix}char_{parameters.Count}"; foreach (var field in searchFields) { // 根据不同策略使用不同的匹配方式 if (strategy == "optimized" && IsChineseCharacter(c)) { // 优化策略:中文单字更宽松 fieldConditions.Add($"({field} LIKE @{paramName} OR {field} LIKE @{paramName}_prefix)"); parameters.Add(new SugarParameter($"@{paramName}", $"%{c}%")); parameters.Add(new SugarParameter($"@{paramName}_prefix", $"{c}%")); } else { fieldConditions.Add($"{field} LIKE @{paramName}"); parameters.Add(new SugarParameter($"@{paramName}", $"%{c}%")); } } charConditions.Add($"({string.Join(" OR ", fieldConditions)})"); } // 根据策略构建条件 string condition; if (requireAll && chars.Length > 1) { // 必须包含所有单字 condition = $"({string.Join(" AND ", charConditions)})"; } else if (!requireAll && chars.Length > 1) { // 任意一个单字即可 condition = $"({string.Join(" OR ", charConditions)})"; } else if (strategy == "optimized" && chars.Length > 2) { // 优化策略:3个以上单字时,至少匹配一半 int requiredCount = (int)Math.Ceiling(chars.Length / 2.0); var orConditions = new List(); // 生成所有可能的组合(限制数量避免爆炸) var combinations = GetCharCombinations(charConditions, chars.Length, requiredCount, 5); foreach (var combination in combinations) { orConditions.Add($"({string.Join(" AND ", combination)})"); } condition = orConditions.Any() ? $"({string.Join(" OR ", orConditions)})" : charConditions.FirstOrDefault() ?? ""; } else { condition = charConditions.FirstOrDefault() ?? ""; } return (condition, parameters); } /// /// 构建精确匹配条件 /// public static (string Condition, List Parameters) BuildExactCondition( string searchTerm, List searchFields, string prefix) { var parameters = new List(); var fieldConditions = new List(); var paramName = $"{prefix}exact"; foreach (var field in searchFields) { fieldConditions.Add($"{field} = @{paramName}"); } string condition = $"({string.Join(" OR ", fieldConditions)})"; parameters.Add(new SugarParameter($"@{paramName}", searchTerm.Trim())); return (condition, parameters); } /// /// 构建开头匹配条件 /// public static (string Condition, List Parameters) BuildPrefixCondition( string searchTerm, List searchFields, string prefix) { var parameters = new List(); var fieldConditions = new List(); var paramName = $"{prefix}prefix"; foreach (var field in searchFields) { fieldConditions.Add($"{field} LIKE @{paramName}"); } string condition = $"({string.Join(" OR ", fieldConditions)})"; parameters.Add(new SugarParameter($"@{paramName}", $"{searchTerm}%")); return (condition, parameters); } /// /// 构建结尾匹配条件 /// public static (string Condition, List Parameters) BuildSuffixCondition( string searchTerm, List searchFields, string prefix) { var parameters = new List(); var fieldConditions = new List(); var paramName = $"{prefix}suffix"; foreach (var field in searchFields) { fieldConditions.Add($"{field} LIKE @{paramName}"); } string condition = $"({string.Join(" OR ", fieldConditions)})"; parameters.Add(new SugarParameter($"@{paramName}", $"%{searchTerm}")); return (condition, parameters); } #endregion #region 智能拆分方法 /// /// 判断是否为可拆分的组合词 /// private static bool IsSplittableCombinationWord(string word) { if (word.Length < 4) return false; // 检查是否由常见的地名+名词等组成 var commonPatterns = new HashSet { "重庆", "北京", "上海", "广州", "深圳", "天津", "武汉", "成都", "杭州", "南京", "科学", "技术", "研究", "发展", "教育", "培训", "管理", "系统", "工程", "设计", "大学", "学院", "学校", "公司", "集团", "中心", "研究所", "实验室", "医院", "银行" }; // 尝试找到明显的组合边界 for (int i = 2; i <= word.Length - 2; i++) { var part1 = word.Substring(0, i); var part2 = word.Substring(i); if (commonPatterns.Contains(part1) || commonPatterns.Contains(part2)) return true; // 检查是否都是常见词汇 if (IsCommonWord(part1) && IsCommonWord(part2)) return true; } return false; } /// /// 拆分组合词 /// private static List SplitCombinationWord(string word) { var result = new List(); if (word.Length <= 2) { result.Add(word); return result; } // 优先按2+2模式拆分(如"重庆科学" -> "重庆", "科学") if (word.Length == 4) { result.Add(word.Substring(0, 2)); result.Add(word.Substring(2, 2)); return result; } // 尝试按常见模式拆分 var commonTwoCharWords = new HashSet { "重庆", "北京", "上海", "广州", "深圳", "天津", "武汉", "成都", "杭州", "南京", "科学", "技术", "研究", "发展", "教育", "培训", "管理", "系统", "工程", "设计", "大学", "学院", "学校", "公司", "集团", "中心", "医院", "银行", "保险", "证券", "软件", "硬件", "网络", "数据", "信息", "智能", "数字", "电子", "通信", "互联网" }; // 检查前缀 for (int i = 2; i <= Math.Min(4, word.Length - 2); i++) { var prefix = word.Substring(0, i); var suffix = word.Substring(i); if (commonTwoCharWords.Contains(prefix) || (i == 2 && IsLikelyWord(prefix))) { result.Add(prefix); // 递归拆分剩余部分 if (suffix.Length >= 2) { var subSplits = SplitCombinationWord(suffix); result.AddRange(subSplits); } else { result.Add(suffix); } return result; } } // 无法智能拆分,按固定长度拆分 int splitLength = word.Length >= 6 ? 3 : 2; for (int i = 0; i < word.Length; i += splitLength) { var part = word.Substring(i, Math.Min(splitLength, word.Length - i)); result.Add(part); } return result; } /// /// 检查是否可能是常见词汇 /// private static bool IsLikelyWord(string word) { if (word.Length != 2) return false; // 检查是否为常见的中文二字词 // 这里可以扩展更复杂的判断逻辑 return IsChineseCharacter(word[0]) && IsChineseCharacter(word[1]); } /// /// 检查是否是常见词汇 /// private static bool IsCommonWord(string word) { // 这里可以扩展更复杂的常见词判断逻辑 // 例如从词典加载、使用统计等 var commonWords = new HashSet { "中国", "国家", "人民", "社会", "经济", "文化", "教育", "科技", "发展", "企业", "公司", "市场", "产品", "服务", "技术", "管理", "工作", "生活" }; return commonWords.Contains(word) || (word.Length == 2 && IsChineseCharacter(word[0]) && IsChineseCharacter(word[1])); } /// /// 按优先级分组条件 /// private static Dictionary> GroupConditionsByPriority( List conditions, List longWords) { var groups = new Dictionary> { ["original"] = new List(), // 原词条件 ["split"] = new List(), // 拆分子词条件 ["chars"] = new List(), // 单字条件 ["normal"] = new List() // 普通词条件 }; // 简单分组逻辑,实际使用中可能需要更复杂的判断 int longWordCount = longWords.Count; int currentIndex = 0; // 原词条件(每个长词一个) for (int i = 0; i < longWordCount && currentIndex < conditions.Count; i++) { groups["original"].Add(conditions[currentIndex]); currentIndex++; } // 拆分子词条件 for (int i = 0; i < longWordCount && currentIndex < conditions.Count; i++) { groups["split"].Add(conditions[currentIndex]); currentIndex++; } // 单字条件 for (int i = 0; i < longWordCount && currentIndex < conditions.Count; i++) { groups["chars"].Add(conditions[currentIndex]); currentIndex++; } // 剩余的都是普通词条件 while (currentIndex < conditions.Count) { groups["normal"].Add(conditions[currentIndex]); currentIndex++; } return groups; } /// /// 构建层次化条件 /// private static string BuildHierarchicalCondition(Dictionary> groups) { var parts = new List(); // 第一层:原词匹配(最高优先级) if (groups["original"].Any()) { parts.Add($"({string.Join(" OR ", groups["original"])})"); } // 第二层:拆分子词匹配 if (groups["split"].Any()) { var splitCondition = groups["split"].Count == 1 ? groups["split"][0] : $"({string.Join(" AND ", groups["split"])})"; parts.Add($"({splitCondition})"); } // 普通词条件(插入到合适位置) if (groups["normal"].Any()) { var normalCondition = groups["normal"].Count == 1 ? groups["normal"][0] : $"({string.Join(" AND ", groups["normal"])})"; // 如果已经有原词条件,放在第二层;否则放在第一层 if (parts.Count >= 1) parts.Insert(1, normalCondition); else parts.Add(normalCondition); } // 第三层:单字匹配(最低优先级) if (groups["chars"].Any()) { var charCondition = groups["chars"].Count == 1 ? groups["chars"][0] : $"({string.Join(" OR ", groups["chars"])})"; parts.Add($"({charCondition})"); } if (parts.Count == 0) return string.Empty; if (parts.Count == 1) return parts[0]; // 构建层次化OR条件 return $"({string.Join(" OR ", parts)})"; } /// /// 根据策略构建混合条件 /// private static string BuildMixedConditionByStrategy( List conditions, SearchStructure structure, string strategy) { if (conditions.Count == 1) return conditions[0]; switch (strategy) { case "char_optimized": // 单字优化策略:词语作为主要条件,单字作为增强 return BuildCharOptimizedCondition(conditions, structure); case "word_focused": // 词语聚焦策略:词语必须,单字作为加分 return BuildWordFocusedCondition(conditions, structure); case "strict_mixed": // 严格混合:所有条件必须满足 return BuildStrictCondition(conditions, structure); case "balanced_mixed": // 平衡混合:词语必须,单字推荐 return BuildBalancedCondition(conditions, structure); case "loose_mixed": // 宽松混合:任意条件满足即可 return BuildLooseCondition(conditions, structure); default: return BuildBalancedCondition(conditions, structure); } } /// /// 构建单字优化条件 /// private static string BuildCharOptimizedCondition(List conditions, SearchStructure structure) { var wordConditions = conditions .Where((c, i) => i < structure.Words.Count) .ToList(); var charConditions = conditions .Skip(structure.Words.Count) .ToList(); if (wordConditions.Any() && charConditions.Any()) { // 词语必须,单字作为重要补充(至少匹配一定比例) if (charConditions.Count > 2) { // 多个单字时,要求至少匹配一半 int requiredChars = (int)Math.Ceiling(charConditions.Count / 2.0); var charCombinations = GetConditionCombinations(charConditions, requiredChars, 3); if (charCombinations.Any()) { var charCombinationStrings = charCombinations .Select(comb => $"({string.Join(" AND ", comb)})") .ToList(); return $"({string.Join(" AND ", wordConditions)} AND ({string.Join(" OR ", charCombinationStrings)}))"; } } return $"({string.Join(" AND ", wordConditions)} AND ({string.Join(" OR ", charConditions)}))"; } else if (charConditions.Any()) { // 只有单字时,至少匹配一半 if (charConditions.Count > 1) { int requiredChars = (int)Math.Ceiling(charConditions.Count / 2.0); var combinations = GetConditionCombinations(charConditions, requiredChars, 3); if (combinations.Any()) { var combinationStrings = combinations .Select(comb => $"({string.Join(" AND ", comb)})") .ToList(); return $"({string.Join(" OR ", combinationStrings)})"; } } return $"({string.Join(" OR ", charConditions)})"; } return conditions.FirstOrDefault() ?? ""; } /// /// 构建词语聚焦条件 /// private static string BuildWordFocusedCondition(List conditions, SearchStructure structure) { var wordConditions = conditions .Where((c, i) => i < structure.Words.Count) .ToList(); var charConditions = conditions .Skip(structure.Words.Count) .ToList(); if (wordConditions.Any() && charConditions.Any()) { // 词语必须满足,单字作为加分项(OR连接) return $"({string.Join(" AND ", wordConditions)} AND ({string.Join(" OR ", charConditions)}))"; } return $"({string.Join(" AND ", conditions)})"; } /// /// 获取条件组合(限制数量避免爆炸) /// private static List> GetConditionCombinations( List conditions, int requiredCount, int maxCombinations = 10) { var result = new List>(); if (conditions.Count <= requiredCount || conditions.Count <= 1) { result.Add(conditions); return result; } // 生成C(n, requiredCount)组合,但限制数量 var indices = Enumerable.Range(0, conditions.Count).ToArray(); var combinations = GetCombinations(indices, requiredCount, maxCombinations); foreach (var combination in combinations) { var selectedConditions = combination .Select(idx => conditions[idx]) .ToList(); result.Add(selectedConditions); } return result; } /// /// 获取字符条件组合 /// private static List> GetCharCombinations( List charConditions, int totalChars, int requiredCount, int maxCombinations) { return GetConditionCombinations(charConditions, requiredCount, maxCombinations); } /// /// 获取索引组合(算法) /// private static List> GetCombinations(int[] indices, int k, int maxCombinations) { var result = new List>(); var combination = new List(); void Backtrack(int start) { if (result.Count >= maxCombinations) return; if (combination.Count == k) { result.Add(new List(combination)); return; } for (int i = start; i < indices.Length; i++) { combination.Add(indices[i]); Backtrack(i + 1); combination.RemoveAt(combination.Count - 1); if (result.Count >= maxCombinations) break; } } Backtrack(0); return result; } #endregion #region 分析工具方法 /// /// 分析搜索词结构 /// public static SearchStructure AnalyzeSearchStructure(string searchTerm) { var structure = new SearchStructure { OriginalTerm = searchTerm, CleanTerm = searchTerm.Trim(), AnalyzedAt = DateTime.Now }; // 移除分隔符获取所有字符 var cleanTerm = RemoveSeparators(searchTerm); structure.AllCharacters = cleanTerm.ToCharArray().ToList(); // 分割成词条(保持原始分割) var separators = new[] { ' ', ',', '、', ',', ';', ';', '|', '/', '\\' }; var rawSegments = searchTerm.Split(separators, StringSplitOptions.RemoveEmptyEntries) .Select(s => s.Trim()) .Where(s => !string.IsNullOrEmpty(s)) .ToList(); structure.Segments = rawSegments; // 分析每个段落的类型 foreach (var segment in rawSegments) { if (segment.Length == 1 && IsChineseCharacter(segment[0])) { structure.SingleChars.Add(segment); structure.HasSingleChars = true; } else { structure.Words.Add(segment); structure.HasWords = true; } } // 设置组合类型 if (structure.HasWords && structure.HasSingleChars) { structure.CombinationType = CombinationType.WordsAndChars; structure.Notes = "混合查询:包含词语和单字"; } else if (structure.HasWords && !structure.HasSingleChars) { structure.CombinationType = CombinationType.WordsOnly; structure.Notes = structure.Words.Count > 1 ? "多词查询" : "单词查询"; } else if (!structure.HasWords && structure.HasSingleChars) { structure.CombinationType = CombinationType.CharsOnly; structure.Notes = structure.SingleChars.Count > 1 ? "多字查询" : "单字查询"; } else { structure.CombinationType = CombinationType.Unknown; structure.Notes = "无法识别的查询类型"; } // 计算复杂度评分 structure.ComplexityScore = CalculateComplexityScore(structure); return structure; } /// /// 计算搜索复杂度评分 /// private static int CalculateComplexityScore(SearchStructure structure) { int score = 0; // 词条数量(1-5分) int segmentCount = structure.Words.Count + structure.SingleChars.Count; score += Math.Min(segmentCount, 5); // 是否混合类型(加3分) if (structure.HasWords && structure.HasSingleChars) score += 3; // 单字数量(每3个加1分,最多2分) if (structure.SingleChars.Count >= 3) score += Math.Min(structure.SingleChars.Count / 3, 2); // 词语平均长度(长词加2分) if (structure.Words.Any()) { double avgLength = structure.Words.Average(w => w.Length); if (avgLength > 4) score += 2; } // 总字符数(10个以上加1分) if (structure.AllCharacters.Count > 10) score += 1; return Math.Min(score, 10); // 最高10分 } /// /// 获取搜索策略 /// private static MatchStrategy GetMatchStrategy(SearchStructure structure, SearchConfig config) { var complexity = CalculateComplexityScore(structure); return new MatchStrategy { StrategyName = complexity >= 7 ? "strict" : complexity >= 4 ? "balanced" : "loose", ComplexityScore = complexity, UseExactMatch = config.EnableExactMatch && structure.Words.Any(w => w.Length >= 3), UsePrefixMatch = config.EnablePrefixMatch, UseFuzzySearch = config.EnableFuzzySearch, UseCharSearch = config.EnableCharSearch && structure.SingleChars.Any(), UseSmartSplitting = config.EnableSmartSplitting && structure.Words.Any(w => w.Length >= config.MinSplitLength), RecommendedPageSize = complexity >= 7 ? 10 : 20 }; } /// /// 获取计分规则 /// private static List GetScoringRules(SearchStructure structure, SearchConfig config) { var rules = new List(); // 词语匹配规则 foreach (var word in structure.Words) { rules.Add(new ScoringRule { Type = "word", Value = word, BaseScore = 10, Bonus = word.Length >= 3 ? 5 : 2, Multiplier = 1.0, Condition = $"包含词语'{word}'" }); } // 单字匹配规则 foreach (var ch in structure.SingleChars) { rules.Add(new ScoringRule { Type = "char", Value = ch, BaseScore = 3, Bonus = 1, Multiplier = 1.0, Condition = $"包含单字'{ch}'" }); } // 混合匹配奖励 if (structure.HasWords && structure.HasSingleChars) { rules.Add(new ScoringRule { Type = "combo", Value = "words_and_chars", BaseScore = 0, Bonus = 8, Multiplier = 1.2, Condition = "同时匹配词语和单字" }); } // 智能拆分奖励 if (config.EnableSmartSplitting && structure.Words.Any(w => w.Length >= config.MinSplitLength)) { rules.Add(new ScoringRule { Type = "smart_split", Value = "smart_split_match", BaseScore = 0, Bonus = 5, Multiplier = 1.1, Condition = "智能拆分匹配" }); } // 完全匹配奖励 rules.Add(new ScoringRule { Type = "exact", Value = "exact_match", BaseScore = 0, Bonus = 15, Multiplier = 1.5, Condition = "完全匹配搜索词" }); return rules; } /// /// 获取需要提升权重的字段 /// private static List GetBoostFields(SearchStructure structure, List searchFields) { var boostFields = new List(); if (structure.HasWords && structure.Words.Any(w => w.Length >= 2)) { // 长词语在名称字段中效果更好 boostFields.AddRange(searchFields.Where(f => f.Contains("name", StringComparison.OrdinalIgnoreCase) || f.Contains("title", StringComparison.OrdinalIgnoreCase) || f.Contains("subject", StringComparison.OrdinalIgnoreCase))); } if (structure.HasSingleChars) { // 单字在描述、内容字段中效果更好 boostFields.AddRange(searchFields.Where(f => f.Contains("desc", StringComparison.OrdinalIgnoreCase) || f.Contains("content", StringComparison.OrdinalIgnoreCase) || f.Contains("remark", StringComparison.OrdinalIgnoreCase) || f.Contains("note", StringComparison.OrdinalIgnoreCase))); } return boostFields.Distinct().ToList(); } /// /// 计算预期匹配数 /// private static int CalculateExpectedMatches(SearchStructure structure, int fieldCount) { int baseMatches = structure.Words.Count + structure.SingleChars.Count; int expected = baseMatches * fieldCount; // 调整预期值 if (structure.CombinationType == CombinationType.WordsAndChars) expected = (int)(expected * 1.5); else if (structure.CombinationType == CombinationType.CharsOnly) expected = (int)(expected * 0.7); return Math.Max(expected, 1); } #endregion #region 条件构建策略 /// /// 构建严格条件(所有条件必须满足) /// private static string BuildStrictCondition(List conditions, SearchStructure structure) { if (conditions.Count == 1) return conditions[0]; // 词语条件在前,单字条件在后 var wordConditions = conditions .Where((c, i) => i < structure.Words.Count) .ToList(); var charConditions = conditions .Skip(structure.Words.Count) .ToList(); if (wordConditions.Any() && charConditions.Any()) { return $"({string.Join(" AND ", wordConditions)} AND ({string.Join(" OR ", charConditions)}))"; } return $"({string.Join(" AND ", conditions)})"; } /// /// 构建平衡条件 /// private static string BuildBalancedCondition(List conditions, SearchStructure structure) { if (conditions.Count == 1) return conditions[0]; // 词语优先,单字作为增强 if (structure.HasWords && structure.HasSingleChars) { var wordCondition = conditions.First(); var charConditions = conditions.Skip(1).ToList(); return $"({wordCondition} AND ({string.Join(" OR ", charConditions)}))"; } return $"({string.Join(" AND ", conditions)})"; } /// /// 构建宽松条件(提高召回率) /// private static string BuildLooseCondition(List conditions, SearchStructure structure) { if (conditions.Count == 1) return conditions[0]; // 所有条件OR连接 return $"({string.Join(" OR ", conditions)})"; } #endregion #region 实用工具方法 /// /// 检查字符是否为中文字符 /// public static bool IsChineseCharacter(char c) { // 基本汉字(0x4E00-0x9FFF) if (c >= 0x4E00 && c <= 0x9FFF) return true; // 扩展A区(0x3400-0x4DBF) if (c >= 0x3400 && c <= 0x4DBF) return true; // 基本汉字补充(0x9FA6-0x9FFF) if (c >= 0x9FA6 && c <= 0x9FFF) return true; return false; } /// /// 移除字符串中的分隔符 /// private static string RemoveSeparators(string text) { if (string.IsNullOrEmpty(text)) return text; var separators = new[] { ' ', ',', '、', ',', ';', ';', '-', '_', '.', '。', '·', '|', '/', '\\' }; return new string(text.Where(c => !separators.Contains(c)).ToArray()); } /// /// 验证搜索字段列表 /// public static (bool IsValid, string Message, List ValidFields) ValidateSearchFields( List searchFields, List allFields) { if (searchFields == null || !searchFields.Any()) return (false, "搜索字段列表不能为空", new List()); if (allFields == null || !allFields.Any()) return (true, "无验证字段列表,接受所有输入", searchFields); var validFields = searchFields.Intersect(allFields).ToList(); var invalidFields = searchFields.Except(allFields).ToList(); if (invalidFields.Any()) { return (false, $"发现无效字段: {string.Join(", ", invalidFields)}", validFields); } return (true, "所有字段有效", validFields); } /// /// 生成搜索统计信息 /// public static SearchStats GenerateSearchStats(SearchStructure structure, int resultCount) { return new SearchStats { SearchTerm = structure.OriginalTerm, CombinationType = structure.CombinationType, WordCount = structure.Words.Count, CharCount = structure.SingleChars.Count, TotalSegments = structure.Segments.Count, ComplexityScore = structure.ComplexityScore, ResultCount = resultCount, GeneratedAt = DateTime.Now }; } #endregion } #region 数据模型和枚举 /// /// 搜索模式枚举 /// public enum SearchMode { /// /// 自动检测搜索类型 /// [Description("自动检测")] AutoDetect = 0, /// /// 单词条搜索 /// [Description("单词条搜索")] SingleWord = 1, /// /// 多词条搜索 /// [Description("多词条搜索")] MultiWord = 2, /// /// 单字搜索 /// [Description("单字搜索")] SingleChar = 3, /// /// 精确匹配 /// [Description("精确匹配")] Exact = 4, /// /// 高级查询 /// [Description("高级查询")] Advanced = 5 } /// /// 组合模式枚举 /// public enum CombinationMode { /// /// 智能混合(自动调整权重和连接方式) /// [Description("智能混合")] SmartMix = 0, /// /// 词语和单字组合(词语必须,单字增强) /// [Description("词语+单字")] WordsAndChars = 1, /// /// 仅词语 /// [Description("仅词语")] WordsOnly = 2, /// /// 仅单字 /// [Description("仅单字")] CharsOnly = 3 } /// /// 组合类型 /// public enum CombinationType { [Description("未知")] Unknown, [Description("仅词语")] WordsOnly, [Description("仅单字")] CharsOnly, [Description("词语和单字混合")] WordsAndChars } /// /// 搜索结构分析结果 /// public class SearchStructure { public string OriginalTerm { get; set; } = ""; public string CleanTerm { get; set; } = ""; public DateTime AnalyzedAt { get; set; } public List Segments { get; set; } = new List(); public List Words { get; set; } = new List(); public List SingleChars { get; set; } = new List(); public List AllCharacters { get; set; } = new List(); public bool HasWords { get; set; } public bool HasSingleChars { get; set; } public CombinationType CombinationType { get; set; } public string Notes { get; set; } = ""; public int ComplexityScore { get; set; } // 统计信息 public int TotalWordLength => Words.Sum(w => w.Length); public int MaxWordLength => Words.Any() ? Words.Max(w => w.Length) : 0; public double AvgWordLength => Words.Any() ? Words.Average(w => w.Length) : 0; public int TotalCharacterCount => AllCharacters.Count; } /// /// 搜索配置类(增强版) /// 控制搜索行为、匹配策略和性能优化的参数集合 /// public class SearchConfig { /// /// 是否启用精确匹配 /// 默认值: true /// 说明: 当设置为true时,系统会尝试使用等号(=)进行完全匹配 /// 适用场景: 搜索ID、编码、精确名称等唯一标识 /// 示例: 搜索"1001"时,只匹配完全等于"1001"的记录 /// 性能影响: 精确匹配通常使用索引,性能最好 /// public bool EnableExactMatch { get; set; } = true; /// /// 是否启用前缀匹配 /// 默认值: true /// 说明: 当设置为true时,系统会尝试匹配以搜索词开头的记录 /// 适用场景: 自动补全、拼音首字母搜索、编码前缀搜索 /// 示例: 搜索"北京"时,会匹配"北京市"、"北京旅游"等 /// 性能影响: 前缀匹配可以使用索引,性能良好 /// public bool EnablePrefixMatch { get; set; } = true; /// /// 是否启用模糊搜索 /// 默认值: true /// 说明: 当设置为true时,系统会使用LIKE '%关键词%'进行模糊匹配 /// 适用场景: 通用全文搜索、包含关系搜索 /// 示例: 搜索"长城"时,会匹配"长城旅游"、"八达岭长城"等 /// 性能影响: 模糊搜索不能使用普通索引,建议配合全文索引使用 /// 注意: 大数据量时可能会影响性能,建议合理设置搜索字段 /// public bool EnableFuzzySearch { get; set; } = true; /// /// 是否启用单字搜索 /// 默认值: true /// 说明: 当设置为true时,系统会将搜索词拆分成单个字符进行匹配 /// 适用场景: 中文单字搜索、记忆不完整的模糊搜索 /// 示例: 搜索"北上广"时,会分别匹配包含"北"、"上"、"广"的记录 /// 注意: 启用后会生成多个LIKE条件,可能影响性能 /// 建议: 单字数量较多时,考虑使用RequireAllChars控制匹配逻辑 /// public bool EnableCharSearch { get; set; } = true; /// /// 是否要求所有词语都必须匹配 /// 默认值: true /// 说明: 当设置为true时,多词搜索中所有词语都必须在记录中出现 /// 当设置为false时,任意一个词语出现即可匹配 /// 适用场景: /// true - 精确搜索,如"北京 长城"要求同时包含"北京"和"长城" /// false - 宽松搜索,如"北京 长城"匹配包含"北京"或"长城"的记录 /// 性能影响: true时可能返回更少结果,但条件更复杂 /// 用户体验: true时结果更精确,false时召回率更高 /// public bool RequireAllWords { get; set; } = true; /// /// 是否要求所有单字都必须匹配 /// 默认值: true /// 说明: 当设置为true时,单字搜索中所有字符都必须在记录中出现 /// 当设置为false时,任意一个字符出现即可匹配 /// 适用场景: /// true - 如"北上广"要求同时包含"北"、"上"、"广" /// false - 如"北上广"匹配包含"北"或"上"或"广"的记录 /// 注意: 单字数量较多时,建议设为false以提高召回率 /// public bool RequireAllChars { get; set; } = true; /// /// 精确匹配的最小长度要求 /// 默认值: 2 /// 说明: 只有当搜索词长度大于等于此值时,才会尝试精确匹配 /// 适用场景: 避免短词(如"a"、"的")使用精确匹配 /// 示例: 设置为3时,"北京"不会使用精确匹配,"北京市"会使用 /// 单位: 字符数 /// 建议值: 2-5之间,根据业务需求调整 /// public int MinExactMatchLength { get; set; } = 2; /// /// 搜索词的最大长度限制 /// 默认值: 200 /// 说明: 超过此长度的搜索词会被自动截断 /// 目的: /// 1. 防止恶意输入导致性能问题 /// 2. 避免过长的SQL语句 /// 3. 提高系统安全性 /// 注意: 实际截断时保留前面部分,不会影响搜索意图 /// 单位: 字符数 /// 建议值: 50-500之间,根据业务场景调整 /// public int MaxSearchTermLength { get; set; } = 200; /// /// 匹配度的最低分数要求 /// 默认值: 0 /// 说明: 只有匹配度分数大于等于此值的记录才会被返回 /// 适用场景: 质量控制,过滤掉相关性太低的结果 /// 分数范围: 通常为0-100,具体取决于评分算法 /// 示例: 设置为10时,匹配度低于10分的记录会被过滤 /// 注意: 需要EnableRelevanceScoring=true才会生效 /// public double MinScore { get; set; } = 0; /// /// 是否启用相关性评分 /// 默认值: true /// 说明: 当设置为true时,系统会计算每条记录的匹配度分数 /// 功能: /// 1. 按匹配度排序(分数高的在前) /// 2. 可以设置MinScore过滤低分记录 /// 3. 提供MatchScore字段供前端显示 /// 性能影响: 会增加计算开销,但用户体验更好 /// 建议: 搜索结果需要排序时启用,简单列表查询可关闭 /// public bool EnableRelevanceScoring { get; set; } = true; /// /// 是否启用分阶段搜索 /// 默认值: false /// 说明: 当设置为true时,系统会按优先级分阶段执行搜索 /// 搜索阶段: /// 1. 精确匹配(最高优先级) /// 2. 前缀匹配 /// 3. 模糊匹配 /// 4. 单字匹配(最低优先级) /// 优点: /// 1. 优先返回最相关的结果 /// 2. 可以设置降级策略 /// 3. 提高搜索成功率 /// 缺点: /// 1. 可能执行多次查询 /// 2. 逻辑更复杂 /// 适用场景: 对搜索结果质量要求较高的场景 /// public bool EnableStagedSearch { get; set; } = false; /// /// 字段权重配置 /// 默认值: 预定义的权重字典 /// 说明: 控制不同字段在匹配度计算中的重要性 /// 权重范围: 建议0.5-2.0之间 /// 示例配置: /// "name": 1.5 // 名称字段权重高 /// "title": 1.5 // 标题字段权重高 /// "code": 1.3 // 编码字段权重中 /// "desc": 1.0 // 描述字段权重正常 /// "remark": 0.7 // 备注字段权重低 /// 使用方式: /// 1. 匹配度分数 = 基础分 × 字段权重 /// 2. 权重高的字段对总分影响更大 /// 建议: 根据业务重要性调整权重 /// public Dictionary FieldWeights { get; set; } = new Dictionary { { "name", 1.5 }, { "title", 1.5 }, { "code", 1.3 }, { "description", 1.0 }, { "content", 0.8 }, { "remark", 0.7 } }; /// /// 是否启用同义词扩展 /// 默认值: false /// 说明: 当设置为true时,系统会自动扩展搜索词的同义词 /// 示例: 搜索"电脑"时,也会搜索"计算机"、"微机"等 /// 实现方式: 需要配合同义词词典使用 /// 优点: 提高召回率,改善搜索体验 /// 缺点: 可能引入不相关结果 /// 适用场景: 专业术语搜索、方言词汇搜索 /// public bool EnableSynonymExpansion { get; set; } = false; /// /// 是否启用拼音搜索 /// 默认值: false /// 说明: 当设置为true时,系统会将中文转换为拼音进行搜索 /// 示例: 搜索"beijing"可以匹配"北京" /// 实现方式: 需要拼音转换库 /// 适用场景: /// 1. 输入拼音搜索中文 /// 2. 首字母搜索(如"bj"匹配"北京") /// 注意: 会增加搜索复杂度和索引大小 /// public bool EnablePinyinSearch { get; set; } = false; /// /// 搜索结果的最大数量限制 /// 默认值: 1000 /// 说明: 限制单次搜索返回的最大记录数 /// 目的: /// 1. 防止返回过多数据影响性能 /// 2. 避免内存溢出 /// 3. 提高响应速度 /// 注意: 分页查询时,此限制针对总记录数 /// 建议值: 500-5000之间,根据系统承载能力调整 /// public int MaxResultCount { get; set; } = 1000; /// /// 是否启用搜索缓存 /// 默认值: false /// 说明: 当设置为true时,相同的搜索条件会使用缓存结果 /// 缓存策略: /// 1. 基于搜索词和参数的哈希值 /// 2. 可设置缓存时间 /// 3. 支持滑动过期 /// 适用场景: /// 1. 热门搜索词 /// 2. 数据更新频率低的场景 /// 3. 性能要求高的搜索 /// 注意: 数据频繁更新时,需要合理设置缓存时间 /// public bool EnableSearchCache { get; set; } = false; /// /// 缓存时间(分钟) /// 默认值: 5 /// 说明: 搜索结果的缓存保留时间 /// 单位: 分钟 /// 使用条件: 需要EnableSearchCache=true /// 建议值: /// - 高频搜索: 1-5分钟 /// - 低频搜索: 10-30分钟 /// - 静态数据: 60分钟以上 /// public int CacheDurationMinutes { get; set; } = 5; /// /// 是否启用搜索词分析 /// 默认值: true /// 说明: 当设置为true时,系统会对搜索词进行智能分析 /// 分析内容: /// 1. 去除停用词(的、了、在等) /// 2. 提取关键词 /// 3. 识别搜索意图 /// 4. 分析词性 /// 优点: 提高搜索准确性和智能性 /// 性能影响: 轻微,主要消耗在分析算法上 /// 建议: 一般保持启用状态 /// public bool EnableQueryAnalysis { get; set; } = true; /// /// 是否记录搜索日志 /// 默认值: false /// 说明: 当设置为true时,系统会记录搜索行为日志 /// 记录内容: /// 1. 搜索词 /// 2. 搜索时间 /// 3. 返回结果数 /// 4. 响应时间 /// 5. 用户信息(可选) /// 用途: /// 1. 分析用户搜索习惯 /// 2. 优化搜索算法 /// 3. 监控搜索性能 /// 4. 安全审计 /// 注意: 涉及隐私时需谨慎处理 /// public bool EnableSearchLogging { get; set; } = false; /// /// 搜索超时时间(秒) /// 默认值: 30 /// 说明: 搜索操作的最大执行时间 /// 目的: /// 1. 防止长时间运行的查询 /// 2. 提高系统稳定性 /// 3. 改善用户体验 /// 单位: 秒 /// 建议值: /// - 实时搜索: 5-10秒 /// - 后台搜索: 30-60秒 /// - 大数据搜索: 120秒以上 /// 注意: 超时后会取消查询,返回已有结果或错误 /// public int SearchTimeoutSeconds { get; set; } = 30; /// /// 是否启用异步搜索 /// 默认值: true /// 说明: 当设置为true时,搜索操作会异步执行 /// 优点: /// 1. 不阻塞主线程 /// 2. 提高并发处理能力 /// 3. 更好的用户体验 /// 适用场景: /// 1. 复杂搜索条件 /// 2. 大数据量搜索 /// 3. 高并发场景 /// 注意: 需要合理的线程管理和资源控制 /// public bool EnableAsyncSearch { get; set; } = true; /// /// 是否启用智能提示 /// 默认值: false /// 说明: 当设置为true时,系统会根据输入提供搜索建议 /// 功能: /// 1. 自动补全 /// 2. 热门搜索建议 /// 3. 相关搜索推荐 /// 4. 拼写纠正 /// 实现方式: 基于搜索历史、词典、算法模型 /// 适用场景: 搜索框智能提示功能 /// 注意: 需要额外的数据处理和存储 /// public bool EnableSmartSuggestions { get; set; } = false; /// /// 是否启用搜索结果高亮 /// 默认值: false /// 说明: 当设置为true时,搜索结果中的匹配部分会被高亮显示 /// 高亮方式: /// 1. HTML标记(如关键词) /// 2. 特殊字符包裹 /// 3. 前端处理 /// 适用场景: 需要突出显示匹配内容的搜索 /// 注意: 会增加数据传输量和前端处理复杂度 /// public bool EnableResultHighlighting { get; set; } = false; /// /// 是否启用搜索结果分组 /// 默认值: false /// 说明: 当设置为true时,搜索结果会按指定字段进行分组 /// 分组方式: /// 1. 按类型分组 /// 2. 按时间分组 /// 3. 按相关度分组 /// 适用场景: /// 1. 多类型混合搜索 /// 2. 时间线展示 /// 3. 分类浏览 /// 注意: 会增加查询复杂度和处理时间 /// public bool EnableResultGrouping { get; set; } = false; /// /// 是否启用智能拆分 /// 默认值: true /// 说明: 当设置为true时,系统会自动将长词拆分成合理的子词组合 /// 适用场景: 搜索"重庆科学"这类组合词时,会自动尝试"重庆"+"科学"的组合 /// 工作方式: /// 1. 检测长度为MinSplitLength及以上的词语 /// 2. 使用智能算法判断是否为可拆分组合词 /// 3. 如果可拆分,生成多层次搜索条件 /// 多层次条件示例: "重庆科学" → /// - 完整词匹配(最高优先级) /// - 拆分子词匹配("重庆" AND "科学") /// - 单字匹配("重" OR "庆" OR "科" OR "学") /// 优点: /// 1. 提高组合词的搜索成功率 /// 2. 保持搜索结果的准确性 /// 3. 提升用户体验 /// 性能影响: 会增加搜索条件复杂度,但能显著提高召回率 /// 建议: 中文搜索场景建议启用 /// public bool EnableSmartSplitting { get; set; } = true; /// /// 智能拆分时是否要求所有子词都匹配 /// 默认值: false /// 说明: 控制智能拆分时对拆分子词的匹配严格度 /// 示例: /// - true: "重庆科学"拆分为"重庆"和"科学",要求同时包含这两个词 /// - false: "重庆科学"拆分为"重庆"和"科学",包含任意一个即可匹配 /// 适用场景: /// true: 需要精确拆分匹配的场景 /// false: 需要提高召回率的场景 /// 建议: 通常设置为false以获得更好的搜索结果覆盖率 /// 注意: 此设置仅影响智能拆分的子词匹配,不影响原始词语匹配 /// public bool RequireAllWordsForSplit { get; set; } = false; /// /// 智能拆分时是否要求所有单字都匹配 /// 默认值: false /// 说明: 控制智能拆分成单字时的匹配严格度 /// 示例: /// - true: "重庆科学"拆分为单字时,要求同时包含"重"、"庆"、"科"、"学" /// - false: "重庆科学"拆分为单字时,包含任意一个单字即可匹配 /// 适用场景: /// true: 需要完全匹配所有单字的严格场景 /// false: 需要宽松匹配以提高召回率的场景 /// 建议: 通常设置为false,因为单字完全匹配要求较高,容易漏掉相关结果 /// 注意: 此设置仅影响智能拆分的单字匹配阶段 /// public bool RequireAllCharsForSplit { get; set; } = false; /// /// 最小拆分长度 /// 默认值: 4 /// 说明: 只有长度大于等于此值的词才会被考虑进行智能拆分 /// 单位: 字符数 /// 示例: /// - 设置为4时,"重庆科学"(4字)会被考虑拆分 /// - 设置为5时,"北京长城游"(5字)会被考虑拆分 /// 适用场景: /// - 较低值(3-4):适用于短词较多的场景 /// - 较高值(5-6):适用于长词较多的专业场景 /// 建议值: /// - 中文搜索: 4 /// - 英文搜索: 8(对应4个英文单词) /// - 混合搜索: 根据主要语言调整 /// 注意: 设置过低可能导致过多词语被拆分,影响性能;设置过高可能错过可拆分的组合词 /// public int MinSplitLength { get; set; } = 4; /// /// 最大拆分组合数 /// 默认值: 3 /// 说明: 限制一个词的最大拆分方式数量,防止组合爆炸 /// 示例: /// - 设置为3时,一个6字词最多尝试3种拆分方式 /// - 设置为1时,只使用最优的拆分方式 /// 适用场景: /// - 性能敏感场景: 1-2 /// - 平衡场景: 3 /// - 准确性优先场景: 5-10 /// 性能影响: 每增加一个拆分组合,会增加一个搜索条件分支 /// 建议: /// - 实时搜索: 1-3 /// - 后台搜索: 3-5 /// - 复杂分析: 5-10 /// 注意: 过高的值可能导致SQL条件过于复杂,影响数据库性能 /// public int MaxSplitCombinations { get; set; } = 3; } /// /// 搜索阶段 /// public class SearchStage { public int Stage { get; set; } public string Name { get; set; } = ""; public string Condition { get; set; } = ""; public List Parameters { get; set; } = new List(); public int Priority { get; set; } public string Description { get; set; } = ""; public bool FallbackToNext { get; set; } = true; } /// /// 相关性信息(增强版) /// public class RelevanceInfo { public SearchStructure SearchStructure { get; set; } public int ExpectedMatches { get; set; } public List BoostFields { get; set; } = new List(); public List ScoringRules { get; set; } = new List(); public MatchStrategy MatchStrategy { get; set; } public DateTime GeneratedAt { get; set; } public bool HasSmartSplitting { get; set; } public List SplittableWords { get; set; } = new List(); } /// /// 匹配策略(增强版) /// public class MatchStrategy { public string StrategyName { get; set; } = ""; public int ComplexityScore { get; set; } public bool UseExactMatch { get; set; } public bool UsePrefixMatch { get; set; } public bool UseFuzzySearch { get; set; } public bool UseCharSearch { get; set; } public bool UseSmartSplitting { get; set; } public int RecommendedPageSize { get; set; } = 20; public string Description { get; set; } = ""; } /// /// 计分规则 /// public class ScoringRule { public string Type { get; set; } = ""; // word, char, combo, exact, smart_split public string Value { get; set; } = ""; public int BaseScore { get; set; } public int Bonus { get; set; } public double Multiplier { get; set; } = 1.0; public string Condition { get; set; } = ""; } /// /// 搜索统计信息 /// public class SearchStats { public string SearchTerm { get; set; } = ""; public CombinationType CombinationType { get; set; } public int WordCount { get; set; } public int CharCount { get; set; } public int TotalSegments { get; set; } public int ComplexityScore { get; set; } public int ResultCount { get; set; } public DateTime GeneratedAt { get; set; } public double MatchRatio => TotalSegments > 0 ? (double)ResultCount / TotalSegments : 0; public string ComplexityLevel => ComplexityScore >= 7 ? "高" : ComplexityScore >= 4 ? "中" : "低"; } #endregion #region 扩展方法 /// /// AdvancedSearchHelper 扩展方法 /// public static class EnhancedSearchExtensions { /// /// 获取组合类型的详细说明 /// public static string GetDetail(this CombinationType type) { return type switch { CombinationType.WordsOnly => "仅使用词语进行搜索,适合精确的关键词匹配", CombinationType.CharsOnly => "仅使用单字进行搜索,适合模糊或记忆不完整的搜索", CombinationType.WordsAndChars => "混合使用词语和单字,提供更灵活的搜索体验", _ => "未知的搜索类型" }; } /// /// 获取搜索模式的推荐使用场景 /// public static string GetUsageScenario(this SearchMode mode) { return mode switch { SearchMode.AutoDetect => "适用于通用搜索场景,系统自动识别最佳搜索方式", SearchMode.SingleWord => "适用于已知确切名称或关键词的搜索", SearchMode.MultiWord => "适用于多个相关关键词的组合搜索", SearchMode.SingleChar => "适用于模糊搜索或拼音首字母搜索", SearchMode.Exact => "适用于需要完全匹配的精确搜索", SearchMode.Advanced => "适用于专业用户的高级搜索需求", _ => "通用搜索场景" }; } } #endregion }