Issue: Trying to do bulk_update AttributeError: 'dict' object has no attribute '_pk'
Author: bgriffen
State: closed
Created: 2021-09-03 02:31:33

I am trying to do a bulk_update using the example provided.

```python
class BaseModel(pw.Model):

    class Meta:
       database = get_testdb('papers.db') 
    pass

class PaperDB(BaseModel):
    pmid = pw.IntegerField(unique=True)
    title = pw.CharField()
    abstract = pw.TextField()
    journal = pw.CharField()
    authors = pw.CharField()
    pubdate = pw.DateField()
    mesh_terms = pw.CharField()
    publication_types = pw.CharField()
    chemical_list = pw.CharField()
    keywords = pw.CharField()
    doi = pw.CharField()
    delete = pw.BooleanField()
    affiliations = pw.CharField()
    pmc = pw.IntegerField()
    other_id = pw.CharField()
    medline_ta = pw.CharField()
    nlm_unique_id = pw.IntegerField()
    issn_linking = pw.CharField()
    country = pw.CharField()
    pubyear = pw.IntegerField()
    pubmonth = pw.IntegerField()
    pubday = pw.IntegerField()


....
# in code
with self.dbase.atomic():
    for idx in range(0, num_papers_update, n_batch): 
        # self.update_l is a list of dictionaries containing info from dataframe
        # self.update_l = dfi.loc[self.update_pmid].reset_index().to_dict('records')
        db.PaperDB.bulk_update(self.update_l[idx:idx+n_batch],fields=[db.PaperDB.pmid,
                                                 db.PaperDB.title,
                                                 db.PaperDB.abstract,
                                                 db.PaperDB.journal,
                                                 db.PaperDB.authors,
                                                 db.PaperDB.pubdate,
                                                 db.PaperDB.mesh_terms,
                                                 db.PaperDB.publication_types,
                                                 db.PaperDB.chemical_list,
                                                 db.PaperDB.keywords,
                                                 db.PaperDB.doi,
                                                 db.PaperDB.delete,
                                                 db.PaperDB.affiliations,
                                                 db.PaperDB.pmc,
                                                 db.PaperDB.other_id,
                                                 db.PaperDB.medline_ta,
                                                 db.PaperDB.nlm_unique_id,
                                                 db.PaperDB.issn_linking,
                                                 db.PaperDB.country,
                                                 db.PaperDB.pubyear,
                                                 db.PaperDB.pubmonth,
                                                 db.PaperDB.pubday])
```

but I am getting this error:

```bash
    264         if ~os.path.exists(self.fname_excludes):
 in update_db(self, current_pmids)
    138                                                              db.PaperDB.publication_types,
    139                                                              db.PaperDB.chemical_list,
--> 140                                                              db.PaperDB.keywords,
    141                                                              db.PaperDB.doi,
    142                                                              db.PaperDB.delete,

~/anaconda3/lib/python3.8/site-packages/peewee.py in bulk_update(cls, model_list, fields, batch_size)
   6350 
   6351         for batch in batches:
-> 6352             id_list = [model._pk for model in batch]
   6353             update = {}
   6354             for field, attr in zip(fields, attrs):

~/anaconda3/lib/python3.8/site-packages/peewee.py in <listcomp>(.0)
   6350 
   6351         for batch in batches:
-> 6352             id_list = [model._pk for model in batch]
   6353             update = {}
   6354             for field, attr in zip(fields, attrs):

AttributeError: 'dict' object has no attribute '_pk'
```

Also do I really have to supply all the fields from the model? Is there a way to just do it on all fields or say the ones being ingested in that item?

It turns out you can't feed it a list of dictionaries like you can with `insert_many`. I worked around it by creating a list of instances. Not sure if this is the best solution to my situation but it works.

```python
updates = []
for u in self.update_l:
    e = db.PaperDB(**u)
    updates.append(e)

with self.dbase.atomic():
    db.PaperDB.bulk_update(updates,fields=self.cols, batch_size=1000)
```


The docs should make this clear: http://docs.peewee-orm.com/en/latest/peewee/api.html#Model.bulk_update

Also note that the way `bulk_update()` is implemented, it uses a couple tricks to try to do it efficiently. **However** it may actually be more performant and simple to just issue an UPDATE for each model instance/row and do this within a transaction. I suggest going with the simplest possible thing until you find that it has become a significant bottleneck.