繁体   English   中英

如何使用 BsonDocument C# .NET 驱动程序在 MongoDB 中将多个投影和查找作为聚合执行?

[英]How to perform multiple projections and lookups as aggregate in MongoDB using BsonDocument C# .NET driver?

我无法通过 C# .NET 驱动程序使用聚合功能来执行多个投影和查找。

这里我需要使用 mongodb C# .NET 驱动程序复制查询。

db.organizations.aggregate([
  {
    "$project": {
      "_id": {
        "$toString": "$_id"
      },
      "Name": "$Name",
      "LastDateUploaded": "$LastDateUploaded",
      "LastDateEvaluated": "$LastDateEvaluated",
      "PriorityId": "$PriorityId"
    }
  },
  {
    "$lookup": {
      "from": "workflows",
      "localField": "_id",
      "foreignField": "Data.OrganizationId",
      "as": "RelatedWorkflows"
    }
  },
  {
    "$lookup": {
      "from": "priorities",
      "localField": "PriorityId",
      "foreignField": "_id",
      "as": "Priority"
    }
  },
  {
    "$unwind": "$Priority"
  },
  {
    "$project": {
      "Name": "$Name",
      "WorkflowCounter": {
        "$size": "$RelatedWorkflows"
      },
      "LastDateUploaded": "$LastDateUploaded",
      "LastDateEvaluated": "$LastDateEvaluated",
      "Priority": "$Priority.Value"
    }
  },
  {
    "$sort": {
      "Priority": -1,
      "WorkflowCounter": 1,
      "LastDateUploaded": -1,
      "LastDateEvaluated": -1
    }
  }
])

我试图做这样的事情:

public class Organization
    {
        [BsonId]
        [BsonRepresentation(BsonType.ObjectId)]
        public string Id {get; set;}
        public string NPOId { get; set; }
        public string Name { get; set; }
        public string Address { get; set; }
        [BsonRepresentation(BsonType.ObjectId)]
        public string PriorityId { get; set; }
        [BsonIgnoreIfDefault]
        public Priority Priority { get; set; }
        public string City { get; set; }
        public string County { get; set; }
        [MaxLength(2)]
        public string State { get; set; }
        [BsonRepresentation(BsonType.ObjectId)]
        public string CountryId { get; set; }
        [BsonIgnoreIfDefault]
        public Country Country { get; set; }
        [MaxLength(5)]
        public string Zip { get; set; }
        public string TaxCode { get; set; }
        public string ParentTaxCode { get; set; }
        [BsonRepresentation(BsonType.ObjectId)]
        public string CharityTypeId { get; set; }
        [BsonRepresentation(BsonType.ObjectId)]
        public string PreferredExtractorId { get; set; }
        [BsonIgnoreIfDefault]
        public User PreferredExtractor{ get; set; }
        [BsonIgnoreIfDefault]
        public CharityType CharityType { get; set; }
        public string URL { get; set; }
        public decimal Revenue { get; set; }
        public decimal Expenses { get; set; }
        public decimal Assets { get; set; }
        public decimal Excess { get; set; }
        public string IRSType { get; set; }
        public string ICPAScore { get; set; }
        public string ICPBScore { get; set; }
        public string[] DefaultRules { get; set; }
        [BsonIgnore]
        public long NumberOfWorkflows { get; set; }
        public DateTime? LastDateUploaded { get; set; }
        public DateTime? LastDateEvaluated { get; set; }
    }

var organizations = db.GetCollection<Organization>("catalog.organizations");
            var aggregation = organizations.Aggregate().Match(_ => true);

            var projectionOne = new BsonDocument {
                { "$project", new BsonDocument { { "_id", new BsonDocument { { "$toString", "$_id" } } } } },
                { "Name", "$Name"},
                { "LastDateUploaded", "$LastDateUploaded" },
                { "LastDateEvaluated", "$LastDateEvaluated"},
                { "PriorityId", "$PriorityId"}
            };

            aggregation.Project(projectionOne);

            aggregation.AppendStage<Organizations>(new BsonDocument {
                { "$lookup", new BsonDocument { { "from", "wcf.workflows" }, { "localField", "_id" }, { "foreignField", "Data.OrganizationId" }, { "as", "RelatedWorkflows" } } }
            });

            aggregation.AppendStage<Organizations>(new BsonDocument {
                { "$lookup", new BsonDocument { { "from", "catalog.priorities" }, { "localField", "PriorityId" }, { "foreignField", "_id" }, { "as", "Priority" } } }
            });

            aggregation.AppendStage<Organizations>(new BsonDocument {
                { "$unwind", "$Priority" }
            });

            aggregation.AppendStage<Organizations>(new BsonDocument {
                { "$project", new BsonDocument { { "Name", "$Name" }, { "WorkflowCounter", new BsonDocument { { "$size", "$RelatedWorkflows" } } } } },
                { "LastDateUploaded", "$LastDateUploaded" },
                { "LastDateEvaluated", "$LastDateEvaluated"},
                { "PriorityValue", "$Priority.Value"}
            });

            aggregation.AppendStage<Organizations>(new BsonDocument {
                { "$sort", new BsonDocument { { "Priority", 1 }, { "WorkflowCounter", 1 }, { "LastDateUploaded", -1 }, { "LastDateEvaluated", -1} } }
            });

            var organizationsList = await aggregation.ToListAsync();

但是这不起作用,例如我反转了排序选项并且总是返回相同的值。 我试图获得 mongo 查询的字符串表示,但我只得到

aggregate([{ "$match" : { } }])

并且不附加聚合定义。

我尝试使用流畅的表示法来执行查找,但我需要使用 ObjectId 和字符串字段来执行查找,因此出于这个原因,我首先在 mongodb 端解析 ObjectId 以使用第一个投影进行字符串处理,似乎没有等价于将 ObjectId 转换为字符串以执行查找(又名连接)的流利符号。

这是查询在 mongo shell 上正常工作的测试证明: https : //mongoplayground.net/p/dKT8uQHjHnd

我希望从 mongo playground 示例中生成的列表中获取第一个文档,但我总是获取集合的第一个元素。

我结束了下一步:

        var organizations = db.GetCollection<Organization>("catalog.organizations");
        var projectionOne = new BsonDocument {
                                                { "$project", new BsonDocument { 
                                                        { "_id", new BsonDocument { { "$toString", "$_id" } } },
                                                        { "Name", "$Name"},
                                                        { "LastDateUploaded", "$LastDateUploaded" },
                                                        { "LastDateEvaluated", "$LastDateEvaluated"},
                                                        { "PriorityId", "$PriorityId"}
                                                    } 
                                                }
        };

        var lookupOne = new BsonDocument {
            { "$lookup", new BsonDocument { { "from", "wfc.workflows" }, { "localField", "_id" }, { "foreignField", "Data.OrganizationId" }, { "as", "RelatedWorkflows" } } }
        };
        var lookupTwo = new BsonDocument {
            { "$lookup", new BsonDocument { { "from", "catalog.priorities" }, { "localField", "PriorityId" }, { "foreignField", "_id" }, { "as", "Priority" } } }
        };
        var unwindTwo = new BsonDocument {
            { "$unwind", "$Priority" }
        };

        var projectionTwo = new BsonDocument {
                                            { "$project", new BsonDocument { 
                                                    { "Name", "$Name" }, 
                                                    { "WorkflowCounter", new BsonDocument { { "$size", "$RelatedWorkflows" } } },
                                                    { "LastDateUploaded", "$LastDateUploaded" },
                                                    { "LastDateEvaluated", "$LastDateEvaluated"},
                                                    { "PriorityValue", "$Priority.Value"}
                                                } 
                                            }
        };

        var sort = new BsonDocument {
            { "$sort", new BsonDocument { { "PriorityValue", -1 }, { "WorkflowCounter", 1 }, { "LastDateUploaded", -1 }, { "LastDateEvaluated", -1} } }
        };

        var aggregation = organizations.Aggregate<OrganizationWithWorkflows>(new [] {projectionOne, lookupOne, lookupTwo, unwindTwo, projectionTwo, sort});

        var organizationsList = await aggregation.ToListAsync();

我创建了这个类来获取最后的投影结果:

 [BsonIgnoreExtraElements]
 public class OrganizationWithWorkflows
 {
      public string Id { get; set; }
      public string Name { get; set; }
      public long WorkflowCounter {get; set;}
      public DateTime? LastDateUploaded { get; set; }
      public DateTime? LastDateEvaluated { get; set; }
      public int PriorityValue { get; set; }
 }

我花了一段时间,但我终于在这里解决了我的挑战,部分是使用 ObjectId 和字符串字段执行查找,应用从 ObjectId 到字符串的强制转换,并在同一查询中应用多个投影和多个查找。

请注意,字段 counter 是包含在结果数组RelatedWorkflows中的元素的大小,但这也可以在 lookupOne 和分组后应用展开以使用表达式{ $sum ,1 }但在在我的情况下,使用上述数组中的 $size 表达式就足够了。

我希望这可以帮助所有那些在理解如何使用BsonDocuments使用 MongoDB 聚合和 C# .NET 驱动程序时遇到一些麻烦的人,因为无法使用流畅的表示法创建此查询,因为将 ObjectId 转换为字符串并使用那个用于 lookupOne 的,也许我在最后一部分上错了,所以如果你知道怎么做,相信我也会很高兴学习它。

为了获得我的解决方案,我从 Mikael Koskinen 找到了这篇很棒的帖子,并阅读了 mongodb 文档以使用表达式$toString

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM