2017-11-07 13 views
-1

特定の条件を持つサブ文書の配列を作成する必要があります。 ipagentlanguageのフィールドがすべて完全に一致する場合は、新しいサブ文書を追加する必要はなく、いずれかが欠落している場合は、新しいサブ文書を作成する必要があります。彼らはデータベースに表示されるよう

しかし、私は$pushでそれを実行しようとするとき、それは

Exception: StrictModeError: Path "ip" is not in schema, strict mode is `true`, and upsert is `true`. 

findOneAndUpdate私を返すには、文書全体を更新し、私のフィールドは設定してください。また、スキーマに表示されるように設定しようとしましたが、同じエラーを返します。

のArray userSchema

metadata: [mongoose.modelSchemas.UserMetaData], 

userMetaDataSchema

var userMetaDataSchema = new mongoose.Schema({ 

    ip: { type: String, default: '' }, 
    agent: { type: String, default: '' }, 
    language: { type: String, default: '' }, 
    userCreated: { 
     id: { type: mongoose.Schema.Types.ObjectId, ref: 'User' }, 
     name: { type: String, default: '' }, 
    } 
    }); 
    app.db.model('UserMetaData', userMetaDataSchema); 
}; 

私は$pushなしUserMetaDataコレクションへの直接的なfindOneAndUpdateを使用しようとすると、それが動作します。コンソールから

結果:

{ 
     "_id" : ObjectId("5a00d35f03fc3eb63cbb1c6f"), 
     "agent" : "Mozilla/5.0 (Windows NT 6.3; Win64; x64; rv:56.0) Gecko/20100101 Firefox/56.0", 
     "ip" : "::ffff:192.168.33.10", 
     "language" : "en-US,en;q=0.5", 
     "userCreated" : { 
       "name" : "user2", 
       "id" : ObjectId("5a00d27a7fdf8e07f40d2123") 
     }, 
     "__v" : 0 
} 

var fieldsToSet = { 
     $push: { 
     metadata: { 
      agent: userAgent, 
      ip: userIp, 
      language: languages, 
      userCreated: { 
      name: req.user.username, 
      id: req.user._id, 
      } 
     } 
     } 
    }; 
    var options = { upsert: true }; 

    User.findOneAndUpdate(conditions, fieldsToSet, options, function(err, user) {.... 

、このような配列を作成するのに好適な方法は何が動作していないクエリ?ありがとうございました。

+0

'メタデータを、この特定の解決策を見つけるカント:[mongoose.modelSchemas.UserMetaData ]、 'まったく間違っています。あなたの意図はここにあります。 1. ** User'モデル内に**メタデータの配列を**埋め込むには? 2. ** User **モデル内で独自のコレクション内の**メタデータオブジェクトを**参照するには?違いを混乱させているように見えます。おそらく、ドキュメントをどのように保存するかを示す必要があります。関連するすべての部分を表示するということは、ここでのクエリ条件でも一致すると思われるものと一致しない可能性が高いからです。 –

+0

定型文で私はサブ文書を保存する方法でした。私は、すべてのデータでドキュメントをオーバーロードし、それを定型文として残したくありませんでした(私は4つ以上の埋め込み配列を持っています)。だから私は2つのオプションがありました - 期限が切れましたが、TTLインデックスは組み込み配列でサポートされていないか、一意のエントリだけを作成するため、埋め込みから参照へのすべてのコードをリファクタリングする必要があります。私が$ pushを使わないとそれを使うと、文書に現れません。私は本当にこれについては分かりません。何らかの文書の情報をたくさん参照するときに、正しい方法はありますか?おそらくそれはまだリファクタリングに値するでしょうか? – ASem

+0

ようこそスタックオーバーフロー。誰かがあなたの質問にコメントを残すとき、通常の理由はあなたの質問には明確化が必要なため、[あなたの質問を編集する]必要があるからです(https:// stackoverflow。あなたが明示的に求められた部分について明確にしてください(詳細については、com/posts/47148415/editを参照)。これは、あなたが「会話に参加している」と信じる代わりに、あなたの質問に**あなたが求めた詳細を表示し**、それに応答して長らくコメントしていないことを意味します。コメントは私たちに何も教えてくれません。 –

答えて

0

ここでエラーがあなたがサブドキュメントを挿入または更新する場合は、2つの異なる事業者の更新および挿入するための$pushため$setでこれを行う必要があるため$push{upsert: true}オプションでfindOneAndUpdateを使用しようとによって引き起こされました。だからここソリューションは、更新のために異なる設定を使用して挿入することである。この溶液に信用を

var conditions = { 
     _id: req.user._id, 
     'metadata.ip': userIp, 
     'metadata.agent': userAgent, 
     'metadata.language': userLanguage, 
     'metadata.userCreated.name': req.user.username 
    }; 
    var fieldsToSet = { 
     $set: { 
     'metadata.$.agent': userAgent, 
     'metadata.$.ip': userIp, 
     'metadata.$.language': userLanguage, 
     } 
    }; 
    var fieldsToPush = { 
     $push: { 
     metadata: { 
      agent: userAgent, 
      ip: userIp, 
      language: userLanguage, 
      userCreated: { 
      id: req.user._id, 
      name: req.user.username, 
      } 
     } 
     } 
    }; 
    var options = { upsert: true }; 
    // check if thare is a match and overwright 
    User.findOneAndUpdate(conditions, fieldsToSet, options, function (err, setdocs) { 

     //if there is no match then push a new subdocument 
     if (setdocs == null) { 
     User.findByIdAndUpdate(req.user._id, fieldsToPush, function (err, pushdocs) { 
     //... 
     }); 
     } 
     else { 
     //.... 
     } 
    }); 
    }); 

Neil Lunnに行く私はちょうど今

関連する問題