2013-05-26 105 views
5

我有一個HBase(v0.94.7)表與單列家族和列隨着時間的推移添加到它。這些列被命名爲它們創建的時間戳,所以除非查詢行,否則我不知道它包含哪些列。HBase RowMutations來替換一行中的所有列

現在給出一行,我想原子刪除此列家族的所有現有列,並添加一組新的列和值。

所以我想用的HBase的的RowMutations,如:

RowMutations mutations = new RowMutations(row); 

//delete the column family 
Delete delete = new Delete(row); 
delete.deleteFamily(cf); 

//add new columns 
Put put = new Put(row); 
put.add(cf, col1, v1); 
put.add(cf, col2, v2); 

//delete column family and add new columns to same family 
mutations.add(delete); 
mutations.add(put); 

table.mutateRow(mutations); 

但這個代碼最終做的是隻刪除列族是什麼,它不會添加新列。預期這種行爲?

如果是這樣,那麼我怎樣才能實現我的目標原子用一組新的列替換列家族的所有列?

這裏是一個相同的測試案例:

import junit.framework.Assert; 
import org.apache.hadoop.conf.Configuration; 
import org.apache.hadoop.hbase.HBaseConfiguration; 
import org.apache.hadoop.hbase.HColumnDescriptor; 
import org.apache.hadoop.hbase.HTableDescriptor; 
import org.apache.hadoop.hbase.TableExistsException; 
import org.apache.hadoop.hbase.client.*; 
import org.apache.hadoop.hbase.util.Bytes; 
import org.junit.Before; 
import org.junit.BeforeClass; 
import org.junit.Test; 

import java.util.NavigableMap; 

public class TestHBaseRowMutations { 
    static String tableName = "nnn"; 
    static byte[] cf1 = Bytes.toBytes("cf1"); 
    static byte[] row = Bytes.toBytes("r1"); 
    static HTablePool hTablePool; 

    @BeforeClass 
    public static void beforeClass() throws Exception { 
     Configuration config = HBaseConfiguration.create(); 
     hTablePool = new HTablePool(config, Integer.MAX_VALUE); 
     HBaseAdmin admin = new HBaseAdmin(config); 
     HTableDescriptor tableDescriptor = new HTableDescriptor(tableName); 
     tableDescriptor.addFamily(new HColumnDescriptor(cf1)); 
     try { 
      admin.createTable(tableDescriptor); 
     } catch (TableExistsException ignored){} 
    } 

    @Before 
    public void before() throws Exception { 
     HTableInterface table = hTablePool.getTable(tableName); 
     try { 
      Delete delete = new Delete(row); 
      table.delete(delete); 
      System.out.println("deleted old row"); 

      Put put = new Put(row); 
      put.add(cf1, Bytes.toBytes("c1"), Bytes.toBytes("v1")); 
      put.add(cf1, Bytes.toBytes("c11"), Bytes.toBytes("v11")); 
      table.put(put); 
      System.out.println("Created row with seed data"); 
     } finally { 
      table.close(); 
     } 
    } 


    @Test 
    public void testColumnFamilyDeleteRM() throws Exception { 
     HTableInterface table = hTablePool.getTable(tableName); 
     try { 
      RowMutations rm =new RowMutations(row); 

      //delete column family cf1 
      Delete delete = new Delete(row); 
      delete.deleteFamily(cf1); 
      rm.add(delete); 
      System.out.println("Added delete of cf1 column family to row mutation"); 

      //add new columns to same column family cf1 
      Put put = new Put(row); 
      put.add(cf1, Bytes.toBytes("c1"), Bytes.toBytes("new_v1")); 
      put.add(cf1, Bytes.toBytes("c11"), Bytes.toBytes("new_v11")); 
      rm.add(put); 
      System.out.println("Added puts of cf1 column family to row mutation"); 

      //atomic mutate the row 
      table.mutateRow(rm); 
      System.out.println("Mutated row"); 

      //now read the column family cf1 back 
      Result result = table.get(new Get(row)); 
      NavigableMap<byte[], byte[]> familyMap = result.getFamilyMap(cf1); 

      //column family cf1 should have 2 columns because of the Put above 
      //------Following assert fails as cf1 does not exist anymore, why does cf1 not exist anymore?------- 
      Assert.assertNotNull(familyMap); 
      Assert.assertEquals(2, familyMap.size()); 
     } finally { 
      table.close(); 
     } 
    } 
} 
+0

難道是你刪除*列家族*,而不是單獨的列本身? –

+0

如上所述,我不知道列名前列,所以是的,我正在用delete.deleteFamily(cf)刪除列列;然後用put.add(cf,col1,v1)添加新列; ... – vinodv26

回答

4

發佈了同樣的問題在HBase的用戶論壇,原來這是HBase的一個bug。

預期的行爲是,如果RowMutation對某個column-family/column/row有一個刪除,然後放入相同的column-family/column/row,則Put也應該被遵守(但這不是目前情況)。在此

HBase的用戶組的討論: http://apache-hbase.679495.n3.nabble.com/Using-RowMutations-to-replace-all-columns-of-a-row-td4045247.html

HBase的JIRA對於相同: https://issues.apache.org/jira/browse/HBASE-8626其也提供補丁。

1

最接近的人可以做的是設置時間戳的投入比上刪除越高:

long now = System.currentTimeMillis(); 

Delete delete = new Delete(row); 
delete.deleteFamily(cf1, now); 

Put put = new Put(row); 
put.add(cf1, col1, now + 1); 

RowMutations mutations = new RowMutations(row); 
mutations.add(delete); 
mutations.add(put); 

table.mutateRow(mutations); 

可悲的是,它意味着一個get的時間戳「現在」將一無所有在專欄家庭。 Source