0

I have some documents in my MongoDB collection, i want to update those documents with the newest values retrieved from an API.

Here is what i tried:

def Updating(Data):

    for x in Data(): 
        Item = Data['item']
        Price = Data['price']

    update = db.col.update_many({}, {"$set":{"item": Item, "price": "Price"}})

Here Data is the data retrieved from the API. Each document should be updated with the new value, so if i have:

 item: First item
    price: 394

   item: Second item
   price: 20

It should be updated with the new price, for example like this:

item: First item
price: 423

item: Second item
price: 25   

The problem with my actual code is that all the documents in the collection are being updated with the same thing, just like a copy and paste applied to all the records, like this:

item: First item
price: 423

item: First item
price: 423

item: First item
price: 394   

I don't understand why is this happening. I tried using update_one and replace_one but both of them will only update one document in the entire collection.

Jack022
  • 867
  • 6
  • 30
  • 91
  • You need to do a for loop, on each iteration you get new value from the API and use `update_one` with this value. – sanyassh Sep 22 '19 at 11:00
  • *"I don't understand why is this happening. ..."* - Because the `{}` is an **empty query** which simply applies to **everything** in the entire collection. The whole point of the *loop* here ( presumably someone pointed you to this before ) is that the *query* needs to actually specifically select *each individual* document you need to *update*. Specifically you really want `bulk_write()` here and only call it once in "batches" of loop iterations of the data. – Neil Lunn Sep 22 '19 at 11:01
  • I suggest looking at [Fast or Bulk Upsert in pymongo](https://stackoverflow.com/a/36213728/2313887) and doing something like `for doc in Data():` in place of the `for doc in collection.find():` from that example. Referencing individual items from the `List` that produces would then be like `doc['item']` in that case. – Neil Lunn Sep 22 '19 at 11:06
  • I'll look into bulk_write @NeilLunn! What i don't understand, is why does it update all the documents with the same value. If i do the same code with insert, it will insert the data as expected, the trouble only comes with update and replace. I've used an empty query because i want to refer to the whole collection, since i need to update every record – Jack022 Sep 22 '19 at 11:12
  • Because `{}` means **ALL DOCUMENTS**. Just like in the example the *query* part would be like `{ "item": doc["item"] }` just as I was saying. Or `UpdateOne({ "field1": 1},{ "$set": { "price": doc["price" } })` to be specific about what you basically need to replace. – Neil Lunn Sep 22 '19 at 11:16
  • In all honesty, I strongly suggest you take a few hours and really read ALL of [MongoDB CRUD Operations](https://docs.mongodb.com/manual/crud/) in the core manual before you write any more code here. Actually forming queries and understanding what `{}` means and the difference from the form I just gave you is pretty much covered in all that basic tutorial. And it's free!!! and has Python code examples as well – Neil Lunn Sep 22 '19 at 11:19
  • Yes but i want to change all the documents. What i don't understand is why does it change all of them with the same thing, instead of changing all of them with the right data – Jack022 Sep 22 '19 at 11:19
  • Yeah, i'm fairly new to MongoDB, so i really need to get a better understanding of the operations – Jack022 Sep 22 '19 at 11:19
  • 2
    Really. Please take the time to read those things. Just like the other comment pointed out as I did **"that's what the loop is for"**. You simply are not using it. `update_many()` is not meant to apply *individual conditions* in the way you want it to. – Neil Lunn Sep 22 '19 at 11:21

0 Answers0