tags:

views:

19

answers:

2

I have a question about object relational updates on join fields.

I am working on a project using codeigniter with datamapper dmz. But I think my problem is with general understanding of ORMs. So fell free to answer with any ORM you know.

I have two tables, Goods and Tags. One good can have many tags. Everything is working, but I am looking for a way to merge tags. Meaning I decide I want to remove tag A and instead have everything that is tagged by it, now be tagged by tag B.

I only have models for the goods and the tags. There is no separate model for the join relationship, as I believe these ORMs were designed to work.

I know how to delete a tag. But I dont know how to reach into the join table to redirect the references since there is no model for the join table. I would rather use the ORM then issuing a raw SQL command.

A: 
  1. Load all the objects with tag A
  2. Remove tag A
  3. Check objects for tag B; if absent, add it
  4. Save all
Jay
A: 

This sounds like something you need to do in the application language. I.e. for Java:

Good myGood = new Good("My Good");
Good yourGood = new Good("Your Good");

Tag mine = new Tag("mine");
Tag yours = new Tag("yours");

myGood.tag(mine);
yourGood.tag(yours);

/** Persist tags to database */
mine.save();
yours.save();

/** Persist goods to database */
myGood.save();
yourGood.save();

/** I take your good */
yourGood.tag(mine);
yourGood.removeTag(yours);

/** Update database */
yourGood.update();

/** Get my goods */
List<Good> myGoods = dao.getGoodsWithTag(mine);
log.info(yourGoods.size());  // 2
log.info(myGoods.get(0));  // "My Good"
log.info(myGoods.get(1));  // "Your Good"

/** Get your goods */
List<Good> yourGoods = dao.getGoodsWithTag(yours);
log.info(yourGoods.size());  // 0

Now this only removes a tag from one object and puts a different one on it. To eliminate a tag from the database completely and replace it with another existing tag, you could repeat those steps in the application language or do it in the database language:

/** Make all of your goods mine */

/** Get your goods */
List<Good> yourGoods = dao.getGoodsWithTag(yours);
for (Good yoursRightNow : yourGoods) {
    yoursRightNow.tag(mine);
    yoursRightNow.removeTag(yours);
    yoursRightNow.update();  // Or do this later as a transaction
}

Or:

/** Make all of your goods mine through SQL */
dao.sendSql("UPDATE goods_tags SET tagId = " + mine.getId() + " WHERE tagId = " + yours.getId() + ";");
dao.sendSql("DELETE FROM tags WHERE tag = \"yours\";");
Andy