字段投影中忽略的 batchSize 字段名称

Posted

技术标签:

【中文标题】字段投影中忽略的 batchSize 字段名称【英文标题】:batchSize field name ignored in Field Projection 【发布时间】:2017-12-19 07:19:52 【问题描述】:

我有一个 user_batch 集合。它包含以下文件:

[
  _id: ObjectId("594baf96256597ec035df23c"),
  name: "Batch 1",
  batchSize: 30,
  users:[]
 ,
 
  _id: ObjectId("594baf96256597ec035df234"),
  name: "Batch 2",
  batchSize: 50,
  users:[]
 ]

在查找查询中,我只想投影 namebatchSize。但是当我从 nodejs 执行 find 查询时,我在查询结果中得到了整个文档。查询:

db.collection('user_batch').find(, name: 1, batchSize: 1).toArray((err, result) => 
  if(err) 
    console.log(err)
  else
    console.log(result)
)

如果我只是通过 name: 1 那么它将投射 _id 和 name。但是如果我通过 batchSize 那么它将返回整个文档。

注意:在 Mongo Shell 中执行此查询时,我没有遇到此问题

【问题讨论】:

您使用的是哪个特定的节点驱动程序版本?只是想确认哪些版本受到影响。 驱动版本 - 2.2.28,mongo - 3.2.14,节点 - 6.9.3 【参考方案1】:

驱动程序错误地将其解释为batchSize 选项并忽略投影语句是正确的。

在现代驱动程序版本中,正确的方法是实际使用.project()“光标方法”。这与其他语言驱动程序实现更加一致。

    db.collection('collection').find()
      .project( name: 1, batchSize: 1)
      .toArray();

作为一个完整的演示:

const mongodb = require('mongodb'),
      MongoClient = mongodb.MongoClient;


(async function() 

  let db;

  try 
    db = await MongoClient.connect('mongodb://localhost/test');

    // New form uses .project() as a cursor method
    let result = await db.collection('collection').find()
      .project( name: 1, batchSize: 1)
      .toArray();

    console.log(JSON.stringify(result,undefined,2));

    // Legacy form confuses this as being a legacy "cursor option"
    let other = await db.collection('collection')
      .find(, name: 1, batchSize: 1 )
      .toArray();

    console.log(JSON.stringify(other,undefined,2));

   catch(e) 
    console.error(e)
   finally 
    db.close()
  

)()

产生输出:

[
  
    "_id": "594baf96256597ec035df23c",
    "name": "Batch 1",
    "batchSize": 30
  ,
  
    "_id": "594baf96256597ec035df234",
    "name": "Batch 2",
    "batchSize": 50
  
]
[
  
    "_id": "594baf96256597ec035df23c",
    "name": "Batch 1",
    "batchSize": 30,
    "users": []
  ,
  
    "_id": "594baf96256597ec035df234",
    "name": "Batch 2",
    "batchSize": 50,
    "users": []
  
]

第一个输出形式是更正后的形式,使用.project()

【讨论】:

【参考方案2】:

Find 的语法已更改。以下是解决此问题所需的知识。本文摘自https://github.com/mongodb/node-mongodb-native/blob/master/CHANGES_3.0.0.md#find

查找

findfindOne 不再支持 fields 参数。您可以获得与以下相同的结果 fields 参数,通过使用 Cursor.prototype.project 或通过传递 projection 属性 在选项对象上。此外,find 不支持像 skiplimit 作为位置参数。您必须在 options 对象中传递这些参数, 或通过Cursor 方法添加它们,例如Cursor.prototype.skip

2.x 语法:

const cursor = coll.find( a: 42 ,  someField: 1 );

3.x 语法:

const cursor = coll.find( a: 42 ).project( someField: 1 );

/* OR */

const cursor = coll.find( a: 42 ,  projection:  someField: 1  );

【讨论】:

以上是关于字段投影中忽略的 batchSize 字段名称的主要内容,如果未能解决你的问题,请参考以下文章

从方法名称禁用查询创建 - 使用投影

数据库的字段名称长度对性能的影响?

Jackson2 Java到Json数组在创建数组时忽略字段名称

BigQuery 加载 JSON 文件:如何忽略或重命名字段?

如何将行号投影到 Linq 查询结果中

通过聚合中的索引投影嵌套数组字段值