草庐IT

mongodb - 我可以在 findOneAndUpdate 的投影中访问位置 $ 运算符吗

coder 2023-10-31 原文

我有这个有效的查询,但我希望文档只显示 network.stations.$ 而不是整个数组。如果我写 fields: network.stations.$,我会得到一个错误。有没有办法让文档只从 [stations] 返回单个元素?

Network.findOneAndUpdate({
  "network.stations.id": req.params.station_Id
}, {
  "network.stations.$.free_bikes": req.body.free_bikes
}, {
  new: true,
  fields: "network.stations"
}, (err, doc) => console.log(doc)) 
// I want doc to somehow point only to a single station instead of 
// several stations like it currently does.

最佳答案

答案是"is",但不是您所期望的那样。正如您在问题中指出的那样,将 network.stations.$ 放在 "fields" 选项中以按位置返回“已修改”文档会引发特定错误:

"cannot use a positional projection and return the new document"

然而,这应该是“提示”,因为当您知道要修改的值是什么时,您并不真正“需要”“新文档”。简单的情况是不返回 "new" 文档,而是返回它的“发现状态”,即“原子修改之前”,并简单地按照您的要求对返回的数据进行相同的修改在声明中应用。

作为一个包含的小演示:

const mongoose = require('mongoose'),
      Schema = mongoose.Schema;

mongoose.Promise = global.Promise;
mongoose.set('debug',true);

const uri = 'mongodb://localhost/test',
      options = { useMongoClient: true };

const testSchema = new Schema({},{ strict: false });

const Test = mongoose.model('Test', testSchema, 'collection');

function log(data) {
  console.log(JSON.stringify(data,undefined,2))
}

(async function() {

  try {

    const conn = await mongoose.connect(uri,options);

    await Test.remove();

    await Test.insertMany([{ a: [{ b: 1 }, { b: 2 }] }]);

    for ( let i of [1,2] ) {
      let result = await Test.findOneAndUpdate(
        { "a.b": { "$gte": 2 } },
        { "$inc": { "a.$.b": 1 } },
        { "fields": { "a.$": 1 } }
      ).lean();

      console.log('returned');
      log(result);

      result.a[0].b = result.a[0].b + 1;
      console.log('modified');
      log(result);

    }

  } catch(e) {
    console.error(e)
  } finally {
    mongoose.disconnect()
  }


})();

产生:

Mongoose: collection.remove({}, {})
Mongoose: collection.insertMany([ { __v: 0, a: [ { b: 1 }, { b: 2 } ], _id: 59af214b6fb3533d274928c9 } ])
Mongoose: collection.findAndModify({ 'a.b': { '$gte': 2 } }, [], { '$inc': { 'a.$.b': 1 } }, { new: false, upsert: false, fields: { 'a.$': 1 } })
returned
{
  "_id": "59af214b6fb3533d274928c9",
  "a": [
    {
      "b": 2
    }
  ]
}
modified
{
  "_id": "59af214b6fb3533d274928c9",
  "a": [
    {
      "b": 3
    }
  ]
}
Mongoose: collection.findAndModify({ 'a.b': { '$gte': 2 } }, [], { '$inc': { 'a.$.b': 1 } }, { new: false, upsert: false, fields: { 'a.$': 1 } })
returned
{
  "_id": "59af214b6fb3533d274928c9",
  "a": [
    {
      "b": 3
    }
  ]
}
modified
{
  "_id": "59af214b6fb3533d274928c9",
  "a": [
    {
      "b": 4
    }
  ]
}

所以我在循环中进行修改,因此您可以看到随着下一次迭代增加已经增加的值,更新实际应用到服务器上。

仅通过省略 "new" 选项,您得到的是处于“匹配”状态的文档,然后返回修改前的文档状态是完全有效的。修改仍然发生。

在这里您需要做的就是依次对代码进行相同的修改。添加 .lean() 使这变得简单,而且它再次完全有效,因为您“知道您要求服务器做什么”。

这比单独的查询要好,因为“单独地”可以通过修改和查询之间的不同更新来修改文档,以仅返回投影的匹配字段。

而且它比返回“所有”元素并稍后过滤更好,因为当您真正想要的只是“匹配元素”时,潜在的可能是一个“非常大的数组”。这当然是真的。

关于mongodb - 我可以在 findOneAndUpdate 的投影中访问位置 $ 运算符吗,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/46063660/

有关mongodb - 我可以在 findOneAndUpdate 的投影中访问位置 $ 运算符吗的更多相关文章

  1. ruby - 为什么我可以在 Ruby 中使用 Object#send 访问私有(private)/ protected 方法? - 2

    类classAprivatedeffooputs:fooendpublicdefbarputs:barendprivatedefzimputs:zimendprotecteddefdibputs:dibendendA的实例a=A.new测试a.foorescueputs:faila.barrescueputs:faila.zimrescueputs:faila.dibrescueputs:faila.gazrescueputs:fail测试输出failbarfailfailfail.发送测试[:foo,:bar,:zim,:dib,:gaz].each{|m|a.send(m)resc

  2. ruby - 使用 Vim Rails,您可以创建一个新的迁移文件并一次性打开它吗? - 2

    使用带有Rails插件的vim,您可以创建一个迁移文件,然后一次性打开该文件吗?textmate也可以这样吗? 最佳答案 你可以使用rails.vim然后做类似的事情::Rgeneratemigratonadd_foo_to_bar插件将打开迁移生成的文件,这正是您想要的。我不能代表textmate。 关于ruby-使用VimRails,您可以创建一个新的迁移文件并一次性打开它吗?,我们在StackOverflow上找到一个类似的问题: https://sta

  3. ruby - 我可以使用 Ruby 从 CSV 中删除列吗? - 2

    查看Ruby的CSV库的文档,我非常确定这是可能且简单的。我只需要使用Ruby删除CSV文件的前三列,但我没有成功运行它。 最佳答案 csv_table=CSV.read(file_path_in,:headers=>true)csv_table.delete("header_name")csv_table.to_csv#=>ThenewCSVinstringformat检查CSV::Table文档:http://ruby-doc.org/stdlib-1.9.2/libdoc/csv/rdoc/CSV/Table.html

  4. ruby-on-rails - 在混合/模块中覆盖模型的属性访问器 - 2

    我有一个包含模块的模型。我想在模块中覆盖模型的访问器方法。例如:classBlah这显然行不通。有什么想法可以实现吗? 最佳答案 您的代码看起来是正确的。我们正在毫无困难地使用这个确切的模式。如果我没记错的话,Rails使用#method_missing作为属性setter,因此您的模块将优先,阻止ActiveRecord的setter。如果您正在使用ActiveSupport::Concern(参见thisblogpost),那么您的实例方法需要进入一个特殊的模块:classBlah

  5. ruby - 续集在添加关联时访问many_to_many连接表 - 2

    我正在使用Sequel构建一个愿望list系统。我有一个wishlists和itemstable和一个items_wishlists连接表(该名称是续集选择的名称)。items_wishlists表还有一个用于facebookid的额外列(因此我可以存储opengraph操作),这是一个NOTNULL列。我还有Wishlist和Item具有续集many_to_many关联的模型已建立。Wishlist类也有:selectmany_to_many关联的选项设置为select:[:items.*,:items_wishlists__facebook_action_id].有没有一种方法可以

  6. ruby - 我可以使用 aws-sdk-ruby 在 AWS S3 上使用事务性文件删除/上传吗? - 2

    我发现ActiveRecord::Base.transaction在复杂方法中非常有效。我想知道是否可以在如下事务中从AWSS3上传/删除文件:S3Object.transactiondo#writeintofiles#raiseanexceptionend引发异常后,每个操作都应在S3上回滚。S3Object这可能吗?? 最佳答案 虽然S3API具有批量删除功能,但它不支持事务,因为每个删除操作都可以独立于其他操作成功/失败。该API不提供任何批量上传功能(通过PUT或POST),因此每个上传操作都是通过一个独立的API调用完成的

  7. ruby - 触发器 ruby​​ 中 3 点范围运算符和 2 点范围运算符的区别 - 2

    请帮助我理解范围运算符...和..之间的区别,作为Ruby中使用的“触发器”。这是PragmaticProgrammersguidetoRuby中的一个示例:a=(11..20).collect{|i|(i%4==0)..(i%3==0)?i:nil}返回:[nil,12,nil,nil,nil,16,17,18,nil,20]还有:a=(11..20).collect{|i|(i%4==0)...(i%3==0)?i:nil}返回:[nil,12,13,14,15,16,17,18,nil,20] 最佳答案 触发器(又名f/f)是

  8. ruby - 有人可以帮助解释类创建的 post_initialize 回调吗 (Sandi Metz) - 2

    我正在阅读SandiMetz的POODR,并且遇到了一个我不太了解的编码原则。这是代码:classBicycleattr_reader:size,:chain,:tire_sizedefinitialize(args={})@size=args[:size]||1@chain=args[:chain]||2@tire_size=args[:tire_size]||3post_initialize(args)endendclassMountainBike此代码将为其各自的属性输出1,2,3,4,5。我不明白的是查找方法。当一辆山地自行车被实例化时,因为它没有自己的initialize方法

  9. ruby - 是否可以覆盖 gemfile 进行本地开发? - 2

    我们的git存储库中目前有一个Gemfile。但是,有一个gem我只在我的环境中本地使用(我的团队不使用它)。为了使用它,我必须将它添加到我们的Gemfile中,但每次我checkout到我们的master/dev主分支时,由于与跟踪的gemfile冲突,我必须删除它。我想要的是类似Gemfile.local的东西,它将继承从Gemfile导入的gems,但也允许在那里导入新的gems以供使用只有我的机器。此文件将在.gitignore中被忽略。这可能吗? 最佳答案 设置BUNDLE_GEMFILE环境变量:BUNDLE_GEMFI

  10. ruby - 我可以将我的 README.textile 以正确的格式放入我的 RDoc 中吗? - 2

    我喜欢使用Textile或Markdown为我的项目编写自述文件,但是当我生成RDoc时,自述文件被解释为RDoc并且看起来非常糟糕。有没有办法让RDoc通过RedCloth或BlueCloth而不是它自己的格式化程序运行文件?它可以配置为自动检测文件后缀的格式吗?(例如README.textile通过RedCloth运行,但README.mdown通过BlueCloth运行) 最佳答案 使用YARD直接代替RDoc将允许您包含Textile或Markdown文件,只要它们的文件后缀是合理的。我经常使用类似于以下Rake任务的东西:

随机推荐