削除機能追加 - nodejsからmongodbの操作を少しづつ改良してみる

  • 今回から、コードは抜粋した箇所の掲載にしますので、コード全体はgithub かダウンロードしたデータを参照いただけたらと思います。

  • 一応、ダウンロード方法も案内しておきます。

git clone https://github.com/atoris1192/qrunch_mongodb_express.git  
cd qrunch_mongodb_express/  
yarn  
git reset --hard 2c90431de01d  
DEBUG=myapp-mongodb:* npm start  
  • 差分ダウンロード
git reset --hard 0fc5ec90fb  
git pull  
git reset --hard 2c90431de01d7  

本題

  • 削除には、一意な番号が必要なので、mongodb の _id を使って削除指定をしています。
  • リストの土台は、新たに /user_list を作ることにします。
  • mongodbのデータをdocs でうけて、userList変数で html 側に渡すだけです。 これは以前 /api/find を呼び出すとリストが出るように以前作成してあるのですが、そこを使おうとするとhtml側のJSが /api/javascripts に貼り付けされて具合が悪いので作り直しました。

  • そして, HTML側で fetch で送られてきたデータを受ける /api/removeuser も作っておきます。

    • httpメソッドは、DELETE にしてありますが、 GET 以外であれば req.body で受けるので同じです。
    • 受けるデータは、今回もオブジェクト形式です。
  • index.js 抜粋

router.get('/user_list', (req, res) => {  
  findDocuments(db)  
    .then(docs => {  
      if(state.debug) console.log('api/find: result ', docs)  
      res.render('user_list', { userList: docs })  
    })  
    .catch(e => console.error(e.message))  
})  

router.delete('/api/removeuser', (req, res) => {  
  const removeData = req.body  
  if(state.debug) {  
    console.log('api/removeuser: ', req.body)  
  }  
  deleteOneDocument({db, removeData })  
    .then(result => {  
      // if (state.debug) console.log(result.result)  
    })  
    .catch(e => console.error(e.message))  
})  
  • 実際の処理部分 deleteOneDocument関数を libAsync.js に作ります。
  • fetch から複数のデータが来ることを想定して、for文で件数分削除処理を繰り返します。
  • 削除は、ユニークな値 mongodb の _id を使っています。
  • libAsync.js 抜粋

    module.exports.deleteOneDocument= async({ db, removeData }) => {  
    const collection = db.collection(colName)  
    const removeDataArray = Object.entries(removeData)  
    
    let r = null  
    for(let item of removeDataArray) {  
      console.log('deleteOneDocument id: ', item[1])  
    
      const obj = {  
        "_id": ObjectId(item[1])  
      }  
         r = await collection.deleteOne(obj)  
    }  
    return r  
    }  
  • fetch側は作る前に、正常に処理できることを確認しておきます。

    • HTTPie でターミナルから、削除をしてみます
http DELETE http://localhost:3000/api/removeuser 0=5c0b9cf57c9086ac76bd2404 1=5c0b9cf57c9086ac76bd2405  

  • 実際削除されたのがわかります。

    • idは、毎回違うので上記idをそのまま使うと削除できません。
  • サーバー側ができたので、html側を作っていきます。

  • user_list.pug

extends layout  

block content  
  .container  
    h1 user list  
    #removeBtn.btn Remove  
    ol.ol  
      li.label.li #[span.list Index] #[span.list Name] #[span.list Age] #[span.list Height] #[span.list Weight] #[span.list mongoId]  

      for item, index in userList  
        li.data.li.  
          #[input(type="checkbox" value=item._id)]  
          #[span.list #{ index }]  
          #[span.list #{ item.name }]  
          #[span.list #{ item.age }]  
          #[span.list #{ item.height }]  
          #[span.list #{ item.age }]  
          #[span.list#mid #{ item._id }]  
  script(src="javascripts/userList.js")  
  • userList.js

document.addEventListener('DOMContentLoaded', () => {  
  'use strict'  

  console.info('-- userList.js log --')  
  const lis = document.querySelectorAll('li.data')  
  const removeBtn = document.querySelector('#removeBtn')  

  let checkArray = []  


  for(let li of lis) {  
    li.addEventListener('change', (e) => {  
      if (e.target.checked) {  
        console.log('checked')  
        checkArray.push(e.target.value)  
      } else {  
        console.log("removed");  
       for(let i=0,length=checkArray.length; i<length; i++)  {  
        if (checkArray[i] === e.target.value) {  
          checkArray.splice(i, 1)  
        }  
       }  
      }  
      console.log(checkArray);  
    })  
  }  


  removeBtn.addEventListener('click', () => {  
      const data = new URLSearchParams()  
      checkArray.forEach((item, index) => {  
        data.set(index, item)  
      })  

      console.log('URLSearcParams ids: ', data.toString())  

      const options = {  
        method: 'DELETE',  
        body : data,  
      }  

      const main = async() => {  
        try {  
          let res = await fetch('http://localhost:3000/api/removeuser', options)  
          if (!res.ok) throw new Error(response.statusText)  
          console.log('res: ', res)  

        } catch(e) {  
          console.error('エラー', e.message)  
        }  
      }  
      main()  
      location.reload()  
    })  

})  
  • html側は、以前作ったものを流用しています。 追加部分はチェックリストでチェックされたvalue に mongodb の _id をセットして 配列で処理をしています。

  • 削除ボタンをクリックしたあとの処理は、_id の配列データを送る前に、key / value の形に整えて fetch に渡します。

  • 素のjavascript で DOM を操作するのは、できれば避けたいところですが、やり方が分かっていたらプラスになるかと思います。

  • 配列処理には時間を結構取られました。(_ _)

  • 今回は、これで終わりにしたいと思います。

  • 次回は、編集かなぁ、 すんなり終わると思った削除処理が予想外だったので、次回はもっと苦戦しそうです。 m(__)m