回答は「はい」ですが、期待しているとおりではありません。
"cannot use a positional projection and return the new document"
あなたが本当に「必要がないので、これはしかし、「ヒント」である必要があります:あなたは、位置的に「改変」文書は、特定のエラーをスロー返すため"fields"
オプションでnetwork.stations.$
を入れて、質問に注意したよう"あなたが値を知っているときに"新しい文書 "を変更しています。単純なケースでは、"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()
を追加すると、これは簡単になります。また、「サーバーに何を依頼したかを知っているから」再び完全に有効です。
これは、別々のクエリよりも優れています。これは、ドキュメントを「別個に」、修正とクエリの間の別の更新によって修正して、投影された一致フィールドのみを返すことができるからです。
そして、すべての要素を戻して後でフィルタリングするよりも、潜在的に「非常に大きな配列」になる可能性があります。もちろん、これは実際にはそうです。
'' projection ''は、[' '.findOneAndUpdate()']のMongoDB "コアドライバ"バージョンのオプションです(https://docs.mongodb.com/v3.2/reference/method/db.collection)。 .findOneAndUpdate /)。 ["mongoose method"](http://mongoosejs.com/docs/api.html#model_Model.findOneAndUpdate)には異なる署名があります。コアドライバでも、変更されたドキュメントから位置投影を返すことはできません。 –
$ setとprojectionプロパティが機能しませんでした。 –
また、あなたが調べた構文も実際には "シェル"構文であることに注意してください。そして '' new "'はシェルにとって有効なオプションではなく、むしろ 'returnNewDocument'になります。そして、「ノードドライバメソッド」(http://mongodb.github.io/node-mongodb-native/2.2/api/Collection.html#findOneAndUpdate)には、 'returnOriginal'というオプションの別の名前があります。もちろん、 "逆"ブール条件です。 「新規文書」を含む位置投影は機能しません。これは私の答えで説明されているものです。 –