【问题标题】:How to do I write a strongly typed filter where nested object properties cannot be equal using C# MongoDB driver?如何使用 C# MongoDB 驱动程序编写一个嵌套对象属性不能相等的强类型过滤器?
【发布时间】:2023-03-24 19:15:01
【问题描述】:
Model:{_id:1, Name:"Ross", Skills: [{ _id:1, SkillName:"Swiming"}, { _id:3, SkillName:"Fishing"}]}

Candidate1:{_id:1, Name:"Ross", Skills: [{ _id:1, SkillName:"Swiming"}, { _id:2, SkillName:"Kayaking"}]}
Candidate2:{_id:2, Name:"Ted", Skills: [{ _id:1, SkillName:"Swiming"}, { _id:3, SkillName:"Fishing"}]}
Candidate3:{_id:3, Name:"Snow", Skills: [{ _id:1, SkillName:"Swiming"}, { _id:1, SkillName:"Swiming"}]}
Candidate4:{_id:4, Name:"Snow", Skills: [ { _id:3, SkillName:"Fishing"}]}

我想过滤掉多次没有相同技能的候选人。 应用过滤器后,我的预期结果是:

Candidate1:{_id:1, Name:"Ross", Skills: [{ _id:1, SkillName:"Swiming"}, { _id:2, SkillName:"Kayaking"}]}
Candidate2:{_id:2, Name:"Ted", Skills: [{ _id:1, SkillName:"Swiming"}, { _id:3, SkillName:"Fishing"}]}   
Candidate4:{_id:4, Name:"Snow", Skills: [ { _id:3, SkillName:"Fishing"}]}

Candidate3 不会被选中,因为他有两次相同的技能。

所以我尝试了这个

filter = Builders<Candidate>.Filter.Where(cndt => cndt.Skills.Count>1 && cndt.Skills[0]._id != cndt.Skills[1]._id );

但这不起作用。 注意:最多可以有两个 Skills

【问题讨论】:

    标签: c# mongodb mongodb-query


    【解决方案1】:

    可以通过将技能数组的大小与一组不同的技能数组进行比较来做到这一点。这可以在 mongo 控制台中使用以下查找查询来表示。

    db.candidates.find({
      "$expr":{
        "$eq":[
          {
            "$size":{
              "$reduce":{
                "input":"$Skills",
                "initialValue":[
                  
                ],
                "in":{
                  "$setUnion":[
                    "$$value",
                    [
                      "$$this._id"
                    ]
                  ]
                }
              }
            }
          },
          {
            "$size":"$Skills"
          }
        ]
      }
    }
    

    这很难使用 C# 类型化的辅助函数来表达,因此值得将其作为字符串过滤器传入。

    var client = new MongoClient();
    var database = client.GetDatabase("test");
    var collection = database.GetCollection<Candidate>("candidates");
    
    var results = await collection.Find(@"{
      ""$expr"":{
        ""$eq"":[
          {
            ""$size"":{
              ""$reduce"":{
                ""input"":""$Skills"",
                ""initialValue"":[
                  
                ],
                ""in"":{
                  ""$setUnion"":[
                    ""$$value"",
                    [
                      ""$$this._id""
                    ]
                  ]
                }
              }
            }
          },
          {
            ""$size"":""$Skills""
          }
        ]
      }
    }").ToListAsync();
    
    foreach (var candidate in results)
    {
       Console.WriteLine($"{candidate.Id}: {candidate.Name}");
    }
    // 1: Ross
    // 2: Ted
    // 4: Snow
    

    这个查询相当复杂,所以这里是它在做什么的细分

    $expr 查询运算符允许我们在查询中使用聚合表达式。

    $size 为我们提供了数组的大小,我们可以在其中将两个大小与$eq 进行比较。

    然后,我们将创建一个带有 $reduce 的新数组,这将是技能 ID 的所有值的联合集。

    【讨论】:

      猜你喜欢
      • 2016-11-16
      • 2017-08-08
      • 1970-01-01
      • 2018-11-16
      • 2016-05-10
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2017-05-09
      相关资源
      最近更新 更多