在C#的MongoDB驱动程序中使用$ addFields [英] Using $addFields in MongoDB Driver for C#

查看:209
本文介绍了在C#的MongoDB驱动程序中使用$ addFields的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我知道这不是一项功能,因此不会按此处所述实现: https: //jira.mongodb.org/browse/CSHARP-1750

I know that this is not a feature and will not be implemented as stated here: https://jira.mongodb.org/browse/CSHARP-1750

但是,我确实需要使用$ addFields运算符执行聚合. 根据对>如何在MongoDB C#中使用Addfields的评论汇总管道

However I really need to execute an aggregation with the $addFields operator. According to the comment on How to use Addfields in MongoDB C# Aggregation Pipeline

jira.mongodb.org/browse/CSHARP-1750.阅读决议无法解决". 给出了推理,但显然根本不在路线图上.如果 您真的想要它,然后手动指定管道 BsonDocument构建器,因为这实际上是所有API方法所做的 反正.和/或投票支持JIRA问题,并提供足够的支持 那么也许有人会认为值得为以后的工作考虑. – Neil Lunn 18年11月3日

jira.mongodb.org/browse/CSHARP-1750. Read the resolution "won't fix". The reasoning is given, but it's clearly not on the roadmap at all. If you really want it then specify the pipeline manually with BsonDocument builders since that's all the API methods actually do anyway. And/Or vote up the JIRA issue, and with sufficient backing then maybe someone will think it worth considering for future work. – Neil Lunn Nov 3 '18

您可以手动构建管道.我将如何去做,是否可以使用之前,甚至可能在手动字符串之后的聚合方式,所以我不必手工构建整个东西,而只需构建addFields部分?

you can manually build the pipeline. How would I go about doing that, and can I use the aggregation I have before, and possibly after the manual string, so I don't have to build the entire thing by hand but only the addFields part?

我尝试过

StringBuilder addFieldsDefinition = new StringBuilder();
addFieldsDefinition.AppendLine("{");
addFieldsDefinition.AppendLine("\"values"":{$reduce: {");
addFieldsDefinition.AppendLine("input: \"$values\",");
addFieldsDefinition.AppendLine("initialValue: {timeStamp: ISODate(\"0000-01-01T00:00:00.000+0000\")},");
addFieldsDefinition.AppendLine("in: {$cond: [{$and : [");
addFieldsDefinition.AppendLine("{$gte : [\"$$this.timeStamp\", \"$$value.timeStamp\"]},");
addFieldsDefinition.AppendLine("{$lte : [\"$$this.timeStamp\", ISODate(\"" + dt.ToString("yyyy-MM-dd") + "T" + dt.ToString("HH:mm:ss.fff") + "\")]}");
addFieldsDefinition.AppendLine("]}, \"$$this"", \"$$value\"]}");
addFieldsDefinition.AppendLine("}}");
addFieldsDefinition.AppendLine("}");

IAggregateFluent<BsonDocument> aggregate = col.Aggregate()
  .Match(filterDef)
  .Project(projectDef);
aggregate.Stages.Add("$addFields : " + addFieldsDefinition .ToString());

想要获取数组中的元素,其中子文档中的"timeStamp"字段最高,但在指定的dateTime下. 但是,当我尝试添加阶段时,该代码向我抛出了一个异常,表示无法将字符串转换为IPipelineStageDefinition.

Wanting to get the Element in an Array where the 'timeStamp' field in the sub-document is the highest but under a specified dateTime. But the Code tosses me an Exception when I try to add the stage, saying a String can't be converted into an IPipelineStageDefinition.

我不想做这样的内置聚合(伪代码)

I do not want to do the built in Aggregations like so (pseudocode)

.Unwind(values).Match(timestamp < dt).Sort(timeStamp).Limit(1)

因为那太慢了.

我现在使用MongoDB.Bson对象创建舞台: VB.NET代码(对不起,我无法手动转换该烂摊子)

I now use the MongoDB.Bson Objects to create the stage: VB.NET Code (Sorry but I can't be bothered to convert that mess by hand)

Dim stage As New BsonDocument(New BsonElement("$addFields", New BsonDocument(New BsonElement("value",
    New BsonDocument(New BsonElement("$reduce", New BsonDocument(New List(Of BsonElement) From
        {
            New BsonElement("input", New BsonString("$" + FieldNames.VALUES_FIELDNAME)),
            New BsonElement("initialValue", New BsonDocument(New BsonElement("timeStamp", New BsonDateTime(DateTime.MaxValue)))),
            New BsonElement("in", New BsonDocument(New List(Of BsonElement) From
                {
                    New BsonElement("$cond", New BsonArray() From
                    {
                        New BsonDocument(New BsonElement("$and", New BsonArray() From
                        {
                            New BsonDocument(New BsonElement("$lte", New BsonArray() From {New BsonString("$$this.timeStamp"), New BsonString("$$value.timeStamp")})),
                            New BsonDocument(New BsonElement("$gte", New BsonArray() From {New BsonString("$$this.timeStamp"), New BsonDateTime(dt)}))
                        })),
                        New BsonString("$$this"),
                        New BsonString("$$value")
                    })
                }
            ))
        }
    ))))
)))

推荐答案

可以将BsonDocument转换为IPipelineStageDefinition.要获取您想要的BsonDocument:

A BsonDocument can be converted into an IPipelineStageDefinition. To get the BsonDocument you want you just want:

var addFieldsDefinitionDoc = BsonDocument.Parse(addFieldsDefinition.ToString());
var stageElement = new BsonElement("$addFields", addFieldsDefinitionDoc);
var stage = new BsonDocument(stageElement)

然后添加它只需使用:

aggregate = aggregate.AppendStage(stage);

我不确定aggregate.Stages.Add是否会做同样的事情,但是我认为 AppendStage可能是更好的方法(尽管我还没有找到任何文档来告诉我正确的做大多数事情的方法是通过反复试验并检查源代码以了解事情如何工作找到的).

I'm not sure if aggregate.Stages.Add would do the same or not but I think AppendStage is probably the better way of doing it (though I've not found any documentation telling me what the right way of doing most things is so this was found through trial and error and inspecting the source to see how things work)...

您甚至可以使用正常的阶段构建器功能添加其他阶段,如下所示:

You can even add additional stages using the normal stage builder functions like so:

aggregate = aggregate.Project(projectionDefinition);

甚至

aggregate = aggregate
    .AppendStage(stage)
    .Project(projectionDefinition);

这篇关于在C#的MongoDB驱动程序中使用$ addFields的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆