skip to Main Content

I created a telegram bot that saves everyone who launched the bot to the pymongo database.
I have this problem: if the user clicks again on the start, there will be an error: pymongo.errors.DuplicateKeyError: [...]
How to process it?

import motor.motor_asyncio
from datetime import datetime
from aiogram import Bot, types
from aiogram.dispatcher import Dispatcher
from aiogram.utils import executor

TOKEN = ''
cluster = motor.motor_asyncio.AsyncIOMotorClient('')
collection = cluster.Dimalexus.BOT

bot = Bot(token=TOKEN)
dp = Dispatcher(bot)

def add_user(user_id, user_name, name):
    date = datetime.now().date()
    collection.insert_one({
        '_id' : user_id,
        'name' : name,
        "username" : user_name,
        "date" : str(date)
        })

@dp.message_handler(commands=['start'])
async def welcome_send_info(message: types.Message):
    await message.reply('привет')
    name = message.from_user.full_name
    user_name = message.from_user.username
    user_id = message.from_user.id
    try:
        add_user(user_id, user_name, name)
    except Exception as e:
        print(e)

if __name__ == "__main__":
    executor.start_polling(dp, skip_updates=True)

Try-except not working

2

Answers


  1. _id is a unique id, you can’t add multiples time.
    Use update with upsert:

    collection.update_one(
        {
           "_id" : user_id
        }, 
        {
           '_id' : user_id,
           'name' : name,
           "username" : user_name,
           "date" : str(date)
        }, upsert=True)
    

    Or you can search for the _id in the database, if already exists, you don’t add.

    Login or Signup to reply.
  2. that is a Duplicate Error that occurs because you’re trying to insert a value that already exists in that document.

    To handle this, you can try using another function instead of insert_one():
    update_one().
    This one is usually used to update a record that already exists, but you can use the parameter upsert = True to insert a new one if no documents with that filter are found.

    As said here the function mainly accepts two arguments and others that are optional:

    1. filter: this one is used to find the record to update;
    2. new_values: the value updated;
    3. upsert: this is the parameter that you need.

    The code that you will need will be:

    def add_user(user_id, user_name, name):
        date = datetime.now().date()
        collection.update_one({
            "_id" : user_id
            }, {
            '_id' : user_id,
            'name' : name,
            "username" : user_name,
            "date" : str(date)
            }, upsert = True)
    

    With this, you will be searching for that ID. If not found it creates a new record, otherwise you’ll be alright with the record already set up 🙂

    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search