2017-05-22 6 views
0

NodeJS + Express + MongoDB(mongoose)でAPIビルドと通信する簡単なアプリケーションがあります。私の質問はAPI側に委ねられています。モンゴーススキーマの動的フィールドを更新する

私はMongoDBの中に格納し、ユーザーの設定にこのスキーマを使用します。

{ 
    user: Number, 
     name: String, 
     lists: { 
      invoices: { 
       year: Number, 
       orderCol: String, 
       order: Number 
      } 
     } 
    } 
} 

ユーザーごとに1つだけの文書が格納値は年によってソートし、濾過し、請求書のリストを表示するには、私のフロントエンドアプリケーションで使用されること、があります。

ドキュメントを更新する必要がありますが、毎回1つのプロパティのみを更新する必要があります。たとえば、APIを呼び出すとorder & orderColを変更せずにuser.lists.invoices.yearを2017に変更できるようにしたいと考えています。

リストのタイプ(invoices)、変更するプロパティ(year)と値(2017)の3つの値をAPIに送信します。

// PUT request with this payload 
{ 
    list: 'invoices', 
    property: 'year', 
    value: 2017 
} 

私はuserフィールドを使用してクエリしています。

router.put('/lists/:usr', (req, res, next) => { 
    var listData = req.body; // listData.list, listData.property, listData.year 
    var usr = req.params.usr; 
    Config.findOneAndUpdate(
     { user: usr }, 
     { $set: { ??? } }, 
     { new: true, upsert: true }, 
     (err, config) => { 
      if (err) return next(err); 
      res.json({ data: config }); 
     } 
    ) 
}) 

可能dupplicates用注:グーグルでの私の検索およびSO常に$オペレータに私を導くが、それは、このためのソリューションだ場合、私は知らない、そしてどのような場合には、私が使用する方法がわかりませんこの場合はそれです。

私は正しいスキーマを設計していないかもしれません。この場合、私はアドバイスが必要です。

答えて

1

私は全体のAPIの構造についてとてもよく分からないが、私は、我々は次のコードで、この特定の問題を解決することができると思う:

Config.findOne({ user: usr }, (err, config) => { 
    if (err) return next(err); 
    // Be careful if config.lists[list] or config.lists[list][property] can be undefined 
    config.lists[list][property] = value; 
    // this might be needed 
    // config.markModified('lists.' + list + '.' + property); 
    config.save(err => { 
    if (err) return next(err); 
    res.json({ data: config }); 
    }); 
}); 

我々は常にいくつかの変更を適用し、最初の文書を見つけることができます更新機能を使用する代わりに、データベースに再度保存する直前に実行します。

また、この種のアップデートAPIはちょっと珍しいようで、うまく動作するかどうかはわかりません。それにもかかわらず、私は検証ミドルウェアを追加することをお勧めします。これは役立つかもしれないような単純なもの:

function validator(req, res, next) { 

    const fields = ['list', 'property', 'value']; 
    if (!fields.every(field => req.body[field] !== undefined)) { 
    return res.status(400).json({ error: 1, msg: fields.join(', ') + ' are required' }); 
    } 

    if (['invoices', 'interests', 'etc'].indexOf(req.body.list) === -1) { 
    return res.status(400).json({ error: 1, msg: 'list is invalid' }); 
    } 

    // More validations here... 

    next(); 
} 

上記の例では、(おそらくAPIの間で共有することが、より一般的なバリミドルウェアを書く必要があります)うまくいけば、それはまだ役に立つアイデアを提供することができ非常にうまくスケールしません。

+0

私にとっては完璧に機能します。説明をありがとう。 – mariogl

関連する問題