You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

多条件规则匹配实现思路咨询:Post字典与数据库规则校验

问题背景与现有局限

首先说明:我并非索要代码或寻求代劳,仅需此类规则的实现思路。

现有视图通过键值对向控制器提交数据,控制器将数据存入Dictionary<string,string> demoData;数据库含Products表(id、name)与Rules表(原存data_key、data_value、product_ID)。

当前实现代码:

public Dictionary<int, string> testC([FromBody]Dictionary<string,string> demoData) { 
    var getRules = AsDynamic(App.Data["Rules"]); // contains Link_datakey, Link_datavalue, Link_product 
    var getProducts = AsDynamic(App.Data["Products"]); // contains Product_id, Product_name 
    Dictionary<int, string> testdict = new Dictionary<int, string>(); 
    var product = 0; 
    foreach(var r in getRules){ 
        if (demoData.ContainsKey(r.Link_datakey)) { 
            if (demoData[r.Link_datakey] == r.Link_datavalue) { 
                product = Convert.ToInt32(r.Link_product); 
                if (!testdict.ContainsKey(product)) { 
                    testdict.Add(product, getProducts.Where(i => i.id_source == r.Link_product).First().Product_name); 
                } 
            } 
        } 
    } 
    return testdict; 
}

该实现存在两大局限:

  1. 仅支持“等于”规则,若需>、<等操作符,需为每种操作编写单独判断;
  2. 仅支持单条件校验,现需支持多条件组合校验(如some_datakey < some_datavalue AND someother_datakey == someother_datavalue),条件数量可变(1-3个)。

我初步设想调整规则表结构为按rule_group_id分组,新增关联rule_group_id与对应产品的表,但不知如何实现多条件校验逻辑,恳请提供实现思路。


实现思路方案

首先你的方向完全没问题,按规则组分组就是实现多条件组合校验的核心,咱们一步步拆解思路:

一、数据库结构调整

先把表结构捋顺,这样后续逻辑才好落地:

  • 新增RuleGroups表:用来存规则组的核心信息,字段包括rule_group_id(主键)、combine_operator(组内条件的组合逻辑,比如AND/OR,毕竟你只需要1-3个条件,这俩足够覆盖大部分场景)、product_id(直接关联对应产品,省得额外建关联表)。
  • 修改原Rules表:新增rule_group_id(外键关联RuleGroups)、condition_operator字段(存单个条件的操作符,比如==、>、<、>=、<=、!=),保留原有的data_key、data_value。

这样结构就清晰了:一个产品对应一个规则组,一个规则组包含1-3个条件,每个条件有自己的判断逻辑,组内条件用AND/OR来组合。

二、核心逻辑实现

1. 封装通用的单条件校验方法

先把不同操作符的判断逻辑封装成一个方法,避免重复写一堆if-else,以后加新操作符直接扩展就行:

private bool IsConditionSatisfied(string inputValue, string ruleValue, string op)
{
    // 先尝试转成数值类型,支持数字比较;转失败就按字符串处理
    if (double.TryParse(inputValue, out double inputNum) && double.TryParse(ruleValue, out double ruleNum))
    {
        return op switch
        {
            "==" => inputNum == ruleNum,
            ">" => inputNum > ruleNum,
            "<" => inputNum < ruleNum,
            ">=" => inputNum >= ruleNum,
            "<=" => inputNum <= ruleNum,
            "!=" => inputNum != ruleNum,
            _ => false
        };
    }
    else
    {
        // 字符串比较,支持大小写不敏感(按需调整)
        return op switch
        {
            "==" => string.Equals(inputValue, ruleValue, StringComparison.OrdinalIgnoreCase),
            "!=" => !string.Equals(inputValue, ruleValue, StringComparison.OrdinalIgnoreCase),
            // 还能扩展比如"contains"、"starts_with"这类字符串操作,按需加
            _ => false
        };
    }
}

2. 规则组的整体校验逻辑

接下来按规则组来处理,每个组代表一组需要一起校验的条件:

  • 先从数据库取出所有规则组,并且关联每个组下的所有条件(也就是1-3条Rule记录)。
  • 遍历每个规则组,先逐个校验组内的条件,收集每个条件的结果。
  • 根据组的组合逻辑(AND/OR)判断整个组是否满足:
    • AND:必须所有条件都满足,才算组匹配。
    • OR:只要有一个条件满足,就算组匹配。
  • 最后把匹配的组对应的产品加入结果字典,注意去重。

大概的逻辑代码(贴合你现有代码的写法):

public Dictionary<int, string> testC([FromBody]Dictionary<string,string> demoData) { 
    // 假设这里能关联查询出每个规则组及其下属的条件
    var ruleGroups = AsDynamic(App.Data["RuleGroups"]).Include("Rules"); 
    var products = AsDynamic(App.Data["Products"]); 
    Dictionary<int, string> matchedProducts = new Dictionary<int, string>(); 

    foreach(var group in ruleGroups)
    {
        bool isGroupMatched = false;
        List<bool> conditionResults = new List<bool>();

        // 逐个校验组内的每个条件
        foreach(var rule in group.Rules)
        {
            if(demoData.ContainsKey(rule.data_key))
            {
                bool result = IsConditionSatisfied(demoData[rule.data_key], rule.data_value, rule.condition_operator);
                conditionResults.Add(result);
            }
            else
            {
                // 如果提交的数据里没有这个key,直接判定该条件不满足
                conditionResults.Add(false);
            }
        }

        // 根据组合逻辑判断整个组是否匹配
        if(group.combine_operator == "AND")
        {
            isGroupMatched = conditionResults.All(r => r); // 所有条件都为true
        }
        else if(group.combine_operator == "OR")
        {
            isGroupMatched = conditionResults.Any(r => r); // 至少一个条件为true
        }

        // 如果组匹配,添加对应的产品到结果(去重)
        if(isGroupMatched)
        {
            int productId = Convert.ToInt32(group.product_id);
            if(!matchedProducts.ContainsKey(productId))
            {
                var targetProduct = products.FirstOrDefault(p => p.id == productId);
                if(targetProduct != null)
                {
                    matchedProducts.Add(productId, targetProduct.name);
                }
            }
        }
    }

    return matchedProducts; 
}

三、后续扩展性建议

  • 可以把操作符做成枚举类型(比如ConditionOperator、CombineOperator),避免字符串硬编码,减少拼写错误的概率。
  • 如果以后需要更复杂的条件嵌套(比如(A AND B) OR C),可以考虑用表达式树动态构建判断逻辑,但对于1-3个条件的场景,上面的方法已经足够简单高效。
  • 给数据库里的rule_group_id、product_id字段加索引,提升查询性能,尤其是数据量变大的时候。

内容的提问来源于stack exchange,提问作者João Gomes

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.11 09:28:09