스마트한 개발 공부/Python

[Python] Mongodb에 저장된 데이터 순차적인 id 값으로 관리하기

스마트한지노 2021. 6. 3. 14:50
728x90
반응형

python flask를 사용해 웹 페이지를 만드는 연습을 했다. 처음에는 mysql을 사용해서 데이터를 저장했다. 다음에는 완성된 웹 페이지의 기능을 그대로 가져와서 mysql이 아닌 Mongo db를 활용하여 다시 만들어보려고 했는데 문제가 발생했다.

mysql에서는 데이터가 저장될 때 id 값이 자동으로 1,2,3 ...으로 순서대로 저장이 됐기 때문에 따로 저장하는 코드가 없이 id 값을 index로 사용할 수 있었다. 
그리고 이 id를 변수로 data를 관리했다. 

하지만, mongo db에서는 id가 object로 저장이 되기 때문에 따로 id값을 지정해줘야 했다. 
또한, id 값을 따로 지정해줘서 데이터를 관리하는 문제점은 순차적으로 id를 구성하지 못하다는 점이다. 

1,2,3,4,5 라는 데이터를 만들었을 때 3이라는 데이터가 지워지면 1,2,4,5 라는 데이터가 남기 때문에 데이터 사이에 id의 간격이 발생한다.

여러가지 방법을 찾아봤는데 일반적으로는 indexing 방법을 사용하지만, 나같은 코딩 초보는 보자마자 따라하는게 쉽지 않았다. 
그래서 다른 방법이 없지 않을까...하고 고민하던 중 괜찮을 방법을 찾아냈다!!


1. 새로운 데이터가 추가될 때, db에 저장된 데이터의 총 개수에 1을 추가한 id를 지정

내가 구현한 add 기능

나는 articles라는 웹페이지를 만들어서 저장된 data를 관리했다. 왼쪽의 하단의 "추가하기" 버튼을 클릭하면 오른쪽의 add_article 페이지로 넘어가서 새로운 데이터를 추가할 수 있다. 

@app.route('/add_article', methods=['GET','POST'])
def add_article():
	db = connect.data
    col = db.topic
    if request.method == "POST":    
        title = request.form['title']
        description = request.form['description']
        author = request.form['author']
        col.insert({
                "id" : col.count()+1,
                "title" : title,
                "description" :description,
                "author" : author})
        return redirect("/articles")
    else:
        return render_template('add_article.html')

코드를 보면 col.insert에서 "'id" 를 db에 있는 데이터의 총 개수를 count 한 뒤에 1을 추가해서 지정해줬다.
이렇게 저장하면 아래와 같은 형태로 db에 저장이 된다. 
[{'_id': ObjectId('60b85d373669eaa7e63c940e'), 'id': 1, 'title': 'title', 'description': 'description', 'author': 'author'}]

데이터를 추가한 모습

테스트를 위해 5개의 데이터를 db에 추가해보았다.
사실 id를 애초에 데이터를 입력받을 때, 사용자가 직접 입력하는 것도 한 가지 방법이다. 처음에는 그런식으로 만들었는데 이러한 방법의 문제점은 중간 데이터가 사라졌을 때 데이터 사이에 간격이 생긴다는 것이다. 

이를 방지하기 위해서 db에 변화가 생길 때마다 각 데이터의 "id" 값을 재설정했다.
(데이터가 많아지면 이렇게 코딩하면 안되겠.....지???)

@app.route('/articles/<id>/delete')
def delete_article(id):
    id = int(id)
    db = connect.data
    col = db.topic
    col.delete_one({'id' : id})
    for i in range(id,col.count()+1):
        col.update_one({"id" :i+1 },{'$set': {"id" :i }})

    return redirect('/articles')
                {% for article in articles %}
                <tr>
                    <td width = "20">{{article["id"]}}</td>
                    <td width = "90"></td> <a href="/article/{{article['id']}}" > {{article['title']}}</a></td>
                    <td>{{article['author']}}</td>
                    <td><a class="btn btn-warning" href="/articles/{{article['id']}}/edit" role="button">EDIT</a></td>
                    <td><a class="btn btn-danger" href="/articles/{{article['id']}}/delete" role="button" onclick="return confirm('정말삭제하시겠습니까?');">DELETE</a></td>
                
                </tr>
                {% endfor %}

delete 버튼을 클릭했을 때, 데이터가 사라지도록 했다. 그리고 for 문을 사용하여 사라진 데이터를 기준으로 그 뒤에 id부터 마지막 id까지를 호출해서 id 번호를 하나씩 땡기도록 만들었다. 

중간 데이터를 삭제해도 id 값이 순차적으로 지정된다.

"Mongodb2" 데이터를 삭제했는데 3, 4, 5번의 id가 하나씩 땡겨진 것을 볼 수 있다. 

좋은 방법은 아니지만, 당장 새로운 것을 시도하기 어려운 분들께 추천하는 방식이다!

728x90
반응형