C ++写入mongo,字符串字段在聚合管道中不起作用

Posted

技术标签:

【中文标题】C ++写入mongo,字符串字段在聚合管道中不起作用【英文标题】:C++ writing to mongo, string fields not working in aggregation pipeline 【发布时间】:2018-12-30 18:16:21 【问题描述】:

** 快速总结:C++ 应用程序使用 OTL4 从 SQL 服务器加载数据,使用 mongocxx bulk_write 写入 Mongo,字符串似乎以某种方式被破坏,因此它们在聚合管道中不起作用(但在其他情况下看起来很好)。 **

我有一个简单的 Mongo 集合,当我投影多个字段时,它似乎与聚合管道的行为不符。这是一个简单的文档,没有嵌套,字段只是双精度和字符串。

前 2 个查询按预期工作:

> db.TemporaryData.aggregate( [  $project :    ParametersId:1   ] )
 "_id" : ObjectId("5c28f751a531251fd0007c72"), "ParametersId" : 526988617 
 "_id" : ObjectId("5c28f751a531251fd0007c73"), "ParametersId" : 526988617 
 "_id" : ObjectId("5c28f751a531251fd0007c74"), "ParametersId" : 526988617 
 "_id" : ObjectId("5c28f751a531251fd0007c75"), "ParametersId" : 526988617 
 "_id" : ObjectId("5c28f751a531251fd0007c76"), "ParametersId" : 526988617 

> db.TemporaryData.aggregate( [  $project :    Col1:1   ] )
 "_id" : ObjectId("5c28f751a531251fd0007c72"), "Col1" : 575 
 "_id" : ObjectId("5c28f751a531251fd0007c73"), "Col1" : 579 
 "_id" : ObjectId("5c28f751a531251fd0007c74"), "Col1" : 616 
 "_id" : ObjectId("5c28f751a531251fd0007c75"), "Col1" : 617 
 "_id" : ObjectId("5c28f751a531251fd0007c76"), "Col1" : 622 

但随后组合不会按预期返回两个字段。

> db.TemporaryData.aggregate( [  $project :    ParametersId:1, Col1:1   ] )
 "_id" : ObjectId("5c28f751a531251fd0007c72"), "ParametersId" : 526988617 
 "_id" : ObjectId("5c28f751a531251fd0007c73"), "ParametersId" : 526988617 
 "_id" : ObjectId("5c28f751a531251fd0007c74"), "ParametersId" : 526988617 
 "_id" : ObjectId("5c28f751a531251fd0007c75"), "ParametersId" : 526988617 
 "_id" : ObjectId("5c28f751a531251fd0007c76"), "ParametersId" : 526988617 

它似乎特定于 ParametersId 字段,例如,如果我选择 2 个其他字段就可以了。

> db.TemporaryData.aggregate( [  $project :    Col1:1, Col2:1   ] )
 "_id" : ObjectId("5c28f751a531251fd0007c72"), "Col1" : 575, "Col2" : "1101-2" 
 "_id" : ObjectId("5c28f751a531251fd0007c73"), "Col1" : 579, "Col2" : "1103-2" 
 "_id" : ObjectId("5c28f751a531251fd0007c74"), "Col1" : 616, "Col2" : "1300-3" 
 "_id" : ObjectId("5c28f751a531251fd0007c75"), "Col1" : 617, "Col2" : "1300-3" 
 "_id" : ObjectId("5c28f751a531251fd0007c76"), "Col1" : 622, "Col2" : "1400-3" 

由于某种原因,当我包含 ParametersId 字段时,管道中的一切都变得松散了:

> db.TemporaryData.aggregate( [  $project :    ParametersId:1, Col2:1, Col1:1, Col3:1   ] )
 "_id" : ObjectId("5c28f751a531251fd0007c72"), "ParametersId" : 526988617, "Col1" : 575 
 "_id" : ObjectId("5c28f751a531251fd0007c73"), "ParametersId" : 526988617, "Col1" : 579 
 "_id" : ObjectId("5c28f751a531251fd0007c74"), "ParametersId" : 526988617, "Col1" : 616 
 "_id" : ObjectId("5c28f751a531251fd0007c75"), "ParametersId" : 526988617, "Col1" : 617 
 "_id" : ObjectId("5c28f751a531251fd0007c76"), "ParametersId" : 526988617, "Col1" : 622 

数据库版本和数据:

> db.version()
4.0.2
> db.TemporaryData.find()
 "_id" : ObjectId("5c28f751a531251fd0007c72"), "CellId" : 998909269, "ParametersId" : 526988617, "Order" : 1, "Col1" : 575, "Col2" : "1101-2", "Col3" : "CHF" 
 "_id" : ObjectId("5c28f751a531251fd0007c73"), "CellId" : 998909269, "ParametersId" : 526988617, "Order" : 1, "Col1" : 579, "Col2" : "1103-2", "Col3" : "CHF" 
 "_id" : ObjectId("5c28f751a531251fd0007c74"), "CellId" : 998909269, "ParametersId" : 526988617, "Order" : 1, "Col1" : 616, "Col2" : "1300-3", "Col3" : "CHF" 
 "_id" : ObjectId("5c28f751a531251fd0007c75"), "CellId" : 998909269, "ParametersId" : 526988617, "Order" : 36, "Col1" : 617, "Col2" : "1300-3", "Col3" : "CHF" 
 "_id" : ObjectId("5c28f751a531251fd0007c76"), "CellId" : 998909269, "ParametersId" : 526988617, "Order" : 1, "Col1" : 622, "Col2" : "1400-3", "Col3" : "CHF" 

更新:引用字段名称没有区别。我在 mongo.exe 命令行中输入了以上所有内容,但我在 C++ 应用程序中看到了相同的行为,但管道稍微复杂一些(投影所有字段以保证顺序)。

这个应用程序实际上首先创建了数据 - 有谁知道可能出错的地方吗?全部使用 mongocxx 库。

** 更新**

原来我对字符串的处理出了点问题。没有数据中的字符串字段,一切都很好。因此,不知何故,我已经弄坏了我的字符串,即使它们在其他方面看起来和行为正确,但它们不能很好地与聚合管道配合使用。我正在使用 mongocxx::collection.bulk_write 编写标准 std::strings,这些标准是通过 OTL4 标头从 sql server 加载的。当它们在内部存储时,中间有一个 strncpy_s 。我似乎无法创建一个简单的可重现示例。

【问题讨论】:

Col1 中可能隐藏了特殊字符,如果您正在复制/粘贴,请尝试手动输入 【参考方案1】:

为了安全起见,不要与其他任何东西发生冲突,请尝试使用具有严格格式的 json 的投影:(为键添加引号)

db.TemporaryData.aggregate( [  $project :    "ParametersId":1, "Col1":1   ] )

【讨论】:

谢谢 - 我刚刚尝试过,但没有任何区别。将更新问题。 我实际上在 3.6 中尝试过这个,我没有遇到任何投影问题。我使用相同的数据,带引号的查询。一切都按预期进行。 :(【参考方案2】:

最后发现问题是文档损坏,因为我使用 bulk_write 进行插入进入数据库但导致了这种奇怪的行为。我切换到使用 insert_many,它抛出了文档已损坏,然后我可以追踪错误。

文档已损坏,因为我多次写入相同的字段值数据,这似乎破坏了我用来构造它们的 bsoncxx::builder::stream::document。

【讨论】:

以上是关于C ++写入mongo,字符串字段在聚合管道中不起作用的主要内容,如果未能解决你的问题,请参考以下文章

C命名管道不适用于多进程

在C中读取和写入结构到管道

将空字符串写入 MongoDB 输出 - Pentaho

《转》'autocomplete="off"'在Chrome中不起作用解决方案

不能在 C 中的管道中写入两次

安全地运行几个字符串替换