2013-05-26 13 views
5

Ho una tabella HBase (v0.94.7) con una sola famiglia di colonne e le colonne vengono aggiunte nel tempo. Queste colonne sono denominate come timestamp in cui sono state create, quindi a meno che non chiedo la riga non so quali siano tutte le colonne.HBase RowMutations per sostituire tutte le colonne di una riga

Ora una riga, voglio atomicamente rimuovere tutte le colonne esistenti di questa famiglia di colonne e aggiungere un nuovo set di colonne e valori.

così ho pensato di usare di RowMutations come HBase:

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); 

Ma ciò che questo codice finisce per fare è solo l'eliminazione della famiglia di colonna, non aggiungere le nuove colonne. È previsto questo comportamento?

Se è così, come posso raggiungere il mio obiettivo atomicamente sostituendo tutte le colonne di una famiglia di colonne con un nuovo set di colonne?

Qui è un banco di prova per lo stesso:

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

Potrebbe essere che si stia eliminando la * famiglia di colonne *, non le singole colonne stesse? –

+0

Come detto sopra, non conosco i nomi delle colonne in anticipo, quindi sì, sto eliminando la famiglia di colonne con delete.deleteFamily (cf); e quindi aggiungendo nuove colonne con put.add (cf, col1, v1); ... – vinodv26

risposta

4

Pubblicato la stessa domanda sul forum degli utenti HBase e risulta questo è un bug in HBase.

Il comportamento previsto è che se una RowMutation ha un Elimina su una colonna-famiglia/colonna/riga seguita da un Put alla stessa colonna-famiglia/colonna/riga, il Put dovrebbe essere onorato (ma questo non è il caso attuale).

HBase discussione di gruppo utente su questo: http://apache-hbase.679495.n3.nabble.com/Using-RowMutations-to-replace-all-columns-of-a-row-td4045247.html

HBase JIRA per la stessa: https://issues.apache.org/jira/browse/HBASE-8626 che fornisce anche patch.

1

Quello più vicino si può fare è impostare il timestamp sul Put essere superiore al Delete:

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); 

Purtroppo, vuol dire che un get al timestamp 'società' non avrà nulla a che famiglia di colonne. Source

Problemi correlati