【问题标题】:Updating array of objects in mongoose based off key in objects value基于对象值中的键更新猫鼬中的对象数组
【发布时间】:2021-05-14 19:56:36
【问题描述】:

我有两个 ejs 表单,当它们被点击时,会向我的 /api/users/makePicks/:id 路由发出 HTTP 发布请求。这条路线到达我的控制器,该控制器使用他们在 EJS 表单中提交的 NFL 选择来更新我的 mongodb 中的用户模型。

我需要这条路线来为每条路线创建picks对象,如果它们在特定的一周内不存在,并且如果它们确实存在,则需要更新已经存在的picks。选择存储在我的用户模型中的一个数组中,该数组包含每周选择的对象。目前,在 Mohammed 的大力帮助下,代码已成功将代码推送到数组。但是,如果存在具有该周键的对象,我似乎无法弄清楚如何更新选择。

我的验证终于正常工作了。我的意思是我们在picks数组上运行一个for循环,如果已经有一个匹配的picks对象与那个星期的picks匹配,它会console.log为真,如果具有当前周形式的第一个键值的对象没有' t 存在,它将 console.log false 并将新选择推送到数组。

唯一不起作用的部分是嵌套在我的 for 循环中的 if 语句,如果对象已经存在于 picks.array 中,它不会更新对象。但正如我所说,验证工作正常。我怀疑这行代码

result.picks[i] = { [`week-${req.params.week}`]:req.body };

由于某种原因没有使用更新的 req.body 更新对象。

控制器

exports.makePicks = async (req, res, next) => {
  const picks = req.body;
  try {
   
    let result = await User.findById(req.user._id);
    
    if (result.picks.length > 0) {
      for (let i = 0; i < result.picks.length; i++) {
        if ((Object.keys(result.picks[i])[0] == [`week-${req.params.week}`])) {
          console.log(chalk.green("true"));
          result.picks[i] = { [`week-${req.params.week}`]:req.body };
          break;
        } else {
          console.log(chalk.red("false"));
          result.picks.push({ [`week-${req.params.week}`]: picks });
          break;
        }
      }
    } else {
      result.picks.push({ [`week-${req.params.week}`]: picks });
      console.log(chalk.yellow('results.picks is empty'))
    }

    
    await result.save();
    res.redirect("/api/dashboard");

  } catch (error) {
    console.log(error);
  }
};

result.picks 示例结构

[{"week-1":
    {"jojo-0":"ARI","jojo-1":"ARI","jojo-2":"ARI"}
},
{"week-2":
    {"jojo-0":"ATL","jojo-1":"ATL","jojo-2":"BAL"}
},
{"week-3":
    {"jojo-0":"ARI","jojo-1":"ARI","jojo-2":"ARI"}
}]

路由器

router.route('/makePicks/:week')
  .post(controller.makePicks);

EJS

<% const teamsArr = ['ARI', 'ATL', 'BAL', 'BUF', 'CAR', 'CHI', 'CIN', 'CLE', 'DAL', 'DEN', 'DET', 'GB', 'HOU', 'IND', 'JAX',
'KC', 'LAC', 'LAR', 'LV', 'MIA', 'MIN', 'NE', 'NO', 'NYG','NYJ', 'PHI', 'PIT', 'SEA', 'SF', 'TB', 'TEN', 'WAS' ] %>

<form class="mt-3 mb-3" method="POST" action="/api/users/makePicks/1">
  <% for(i=0; i < user.bullets; i++){ %>
  <div class="form-group">
    <label for="<%= `${user.name}-${i}` %>">Make your pick for bullet <%= `${i}` %></label>
    <select class="form-control" name="<%= `${user.name}-${i}` %>" id="<%= `${user.name}-${i}` %>">
      <% teamsArr.forEach(team => { %>
        <option value="<%= team %>"><%= team %></option>
      <% }) %>
    </select>
  </div>
  <% }; %>
  <button type="submit" class="btn btn-primary">Save changes</button>
</form>

<form class="mt-3 mb-3" method="POST" action="/api/users/makePicks/2">
  <% for(i=0; i < user.bullets; i++){ %>
  <div class="form-group">
    <label for="<%= `${user.name}-${i}` %>">Make your pick for bullet <%= `${i}` %></label>
    <select class="form-control" name="<%= `${user.name}-${i}` %>" id="<%= `${user.name}-${i}` %>">
      <% teamsArr.forEach(team => { %>
        <option value="<%= team %>"><%= team %></option>
      <% }) %>
    </select>
  </div>
  <% }; %>
  <button type="submit" class="btn btn-primary">Save changes</button>
</form>

【问题讨论】:

    标签: node.js express mongoose ejs crud


    【解决方案1】:

    你想在一个 findByIdAndUpdate 中使用 $push$set,这是不可能的,我更喜欢使用 findById()processsave() 所以试试吧

    exports.makePicks = async (req, res, next) => {
      const picks = req.body;
      try {
        //implementation business logic
        let result = await User.findById(req.user._id)
        if(result.picks && result.picks.length > 0){
          result.picks.forEach(item =>{
            if([`week-${req.params.week}`] in item){
              item[`week-${req.params.week}`] = picks
            }
            else{
              result.picks.push({ [`week-${req.params.week}`] : picks })
            }
          })
        }
        else{
          result.picks.push({ [`week-${req.params.week}`] : picks })
        }
    
        await result.save()
        res.redirect('/api/dashboard');
      } catch (error) {
        console.log(error)
      }
    }
    

    注意:不要同时使用callbackasync/await

    【讨论】:

    • 所以我创建了一个新用户并尝试第一次选择第 1 周,但它没有工作,但是当我登录到一个已经在数据库中选择的用户并为第 2 周进行选择时, 有效。这让我认为 if 语句是无法正常工作的部分。如果可以,请查看更新的代码@Mohammad Yaser Ahmadi!
    • 我相信代码不能正常工作,因为它在picks上运行forEach循环,但是如果picks.length = 0会发生什么?
    • 实际上可能不是,因为如果picks.length = 0,else语句不应该触发。
    • 是的,你说得对,因为 picks.length = 0 我的 cod 不工作,你可以使用 if else,我已经更新了我的答案,但它是一个示例,向你展示实现业务逻辑
    【解决方案2】:
    exports.makePicks = async (req, res, next) => {
      const picks = req.body;
      const { week } = req.params;
      try {
       
        let result = await User.findById(req.user._id);
        const data = { [`week-${week}`]: picks };
        const allPicks = [...result.picks];
        
        if (allPicks.length > 0) {
    
          // Search index of peek
          const pickIndex = _.findIndex(allPicks, (pick) => {
            return Object.keys(pick)[0] == `week-${week}`;
          });
    
          // If found, update it
          if (pickIndex !== -1) {
            console.log(chalk.green("true"));
            allPicks[pickIndex] = data;
          }
    
          // Otherwise, push new pick
          else {
            console.log(chalk.red("false"));
            allPicks.push(data);
          }
    
        } else {
          allPicks.push(data);
          console.log(chalk.yellow('results.picks is empty'))
        }
    
        result.picks = allPicks;
        console.log('allPicks', allPicks);
        
        await result.save();
        res.redirect("/api/dashboard");
      } catch (error) {
        console.log(error);
      }
    };
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2019-09-14
      • 2015-01-13
      • 2021-12-28
      • 2022-08-18
      • 1970-01-01
      • 2020-07-31
      • 2018-09-11
      相关资源
      最近更新 更多