How do I get all the values in HBase given Rowkey values?
val tableName = "myTable"
val hConf = HBaseConfiguration.create()
val hTable = new HTable(hConf, tableName)
val theget= new Get(Bytes.toBytes("1001-A")) // rowkey values (1001-A, 1002-A, 2010-A, ...)
val result = hTable.get(theget)
val values = result.listCells()
The code above only works for one rowkey.
You can use Batch operations. Please refer the link below for Javadoc : Batch Operations on HTable
Another approach is to Scan with a start row key & end row key (First & Last row keys from an sorted ascending set of keys). This makes more sense if there are too many values.
There is htable.get method that take list of Gets:
List<Get> gets = ....
List<Result> results = htable.get(gets)
Related
The first:
I've got dataList from retrofit And insert Room Database.
I want to change dataList(Like insert a element). My Room Database can work because I used OnConflictStrategy.REPLACE. but when I delete dataList some elements, My Room Database can not delete elements.
Dao:
#Insert (onConflict = OnConflictStrategy.REPLACE)
suspend fun insertData(dataList : List<Data>)
Entity:
#Entity
data class Data(
#PrimaryKey val Id : Long,
val Fl : String,
val FlMc : String,
val Dm : String,
val Mc : String,)
ViewModel:
fun insertData(dataList: List<Data>) = viewModelScope.launch {
dataRepository.insertData(dataList)
}
//get data from server
fun getData():LiveData<List<Data>>
Activity:
dataViewModel.getData().observer(this){
dataViewModel.insertData(it)
}
How to resolve this situation except DELETE ALL THEN INSERT
The second:
I want to use a progressbar to indicate that I am inserting dataList
How to get the insert status is working or completed
If I understand correctly, you issue is that you cannot delete because you are building a DataList item but don't know the primary key value as it's generated.
As you haven't shown the DataList entity then assuming it is like:-
#Entity
data class DataList(
#PrimaryKey(autogenerate = true)
val id: Long,
val othercolumns: String
....
)
and if you change from suspend fun insertData(dataList : List<Data>) to suspend fun insertData(dataList : List<Data>): List<Long> (i.e. added the List as the result)
Then you have the values of the id column in the result. In the case above the value is the value of the id column.
If the #PrimaryKey is not an integer type e.g. a String then the long returned WILL NOT be the value of the primary key. It will be a special value known as the rowid.
In short using an integer with primary key makes the column an alias of the rowid. if not an integer primary key then it is not an alias BUT the rowid still exists.
You can still use the rowid to access a specific row as the rowid MUST be a unique value. e.g. (again assuming the above) you could have an #Query such as
#Query("SELECT * FROM the_datalist_table WHERE rowid=:rowid")
suspend fun getDataListById(rowid: Long)
Only of use if you know the rowid though.
You could get rowid's say by using
#Query("SELECT rowid FROM the_datalist_table WHERE othercolumns LIKE :something")
suspend fun getRowidOfSomeDataLists(something: String): List<Long>
still not of great use as the selection criteria would also be able to provide a list of Datalists.
Additional re the comment:-
How to use in viewModel or Activity?
As an example you could do something like :-
fun insertData(dataList: List<Data>) = viewModelScope.launch {
val insertedDataList: ArrayList<Data> = ArrayList()
val insertedIdList = dataRepository.insertData(dataList)
val notInsertedDataList: ArrayList<Data> = ArrayList()
for(i in 0..insertedIdList.size) {
if (insertedIdList[i] > 0) {
insertedDataList.add(
Data(
insertedIdList[i], //<<<<< sets the id as per the returned list of id's
dataList[i].Fl,
dataList[i].FlMc,
dataList[i].Dm,
dataList[i].Mc)
)
} else {
notInsertedDataList.add(
Data(
insertedIdList[i], //<<<<< sets the id as per the returned list of id's WILL BE -1 as not inserted
dataList[i].Fl,
dataList[i].FlMc,
dataList[i].Dm,
dataList[i].Mc
)
)
}
}
val notInsertedCount = notInsertedDataList.size
val insertedCount = insertedDataList.size
}
So you have :-
insertedDataList an ArrayList of the successfully inserted Data's (id was not -1) with the id set accordingly.
notInsertedDataList an ArrayList of the Data's that were not inserted (id was -1) id will be set to -1.
insertedCount an Int with the number inserted successfully.
notInsertedCount and Int with the number not inserted correctly.
DELETE ALL
To delete all rows, unless you extract all rows you can't use the convenience #Delete, as this works on being provided the Object (Data) and selecting the row to delete according to the primary key (id column).
The convenience methods #Delete, #Update, #Insert are written to generate the underlying SQL statement(s) bases upon the object (Entity) passed.
e.g. #Delete(data: Data) would generate the SQL DELETE FROM data WHERE id=?, where ? would be the value of the id field when actually run.
The simpler way to delete all columns is to use the #Query annotation (which handles SQL statements other than SELECT statements). So you could have.
#Query("DELETE FROM data")
fun deleteAllData()
note that this does not the return the number of rows that have been deleted.
I want to create a function that gets the first value of a table field if two other field values match the two given function parameters.
I thought this would be easy. But I found nothing in the internet or M documentation that could solve this.
I don't know if I have to loop through a record or if there is a top level function.
= (val1 as text, val2 as text) as text =>
let
result = if [Field1] = val1 and [Field2] = val2 then [Field3] else ""
in
result
As far as I understand your wish, table and column names are hard coded (i.e. you intend to apply the function only for specific table). Then you may use following approach:
// table
let
t1 = #table({"Field1"}, List.Zip({{"a".."e"}})),
t2 = #table({"Field2"}, List.Zip({{"α".."ε"}})),
join = Table.Join(t1&t1,{}, t2&t2,{}),
add = Table.AddIndexColumn(join, "Field3", 0, 1)
in
add
// func
(val1 as text, val2 as text) => Table.SelectRows(table, each [Field1] = val1 and [Field2] = val2)[Field3]{0}
// result
func("d","β") //31
here is the sql statement I am trying to translate in jpa :
select
id,
act_invalidation_id,
last_modification_date,
title,
case when act_invalidation_id is null then 1 else 0 end as test
from act order by test, last_modification_date desc
The actual translation
Root<Act> act = query.from(Act.class);
builder.selectCase()
.when(builder.isNull(actRoot.get("actInvalidation")), 1)
.otherwise(0).as(Integer.class);
Expression<?> actInvalidationPath = actRoot.get("actInvalidation");
Order byInvalidationOrder = builder.asc(actInvalidationPath);
Path<Date> publicationDate = actRoot.get("metadata").get("publicationDate");
Order byLastModificationDate = builder.desc(publicationDate);
query.select(act).orderBy(byInvalidationOrder, byLastModificationDate);
entityManager.createQuery(query).getResultList();
I try to create a temporary column (named test) of Integer type and orderby this column, then orderby lastmodificationdate. The content of this new column is determined by the value of actInvalidation field.
In short: How to create a temp column with integer values, then order by this temp column in jpa ?
Thank you
I didn't test this but it should work like this:
Root<Act> act = query.from(Act.class);
Expression<?> test = builder.selectCase()
.when(builder.isNull(actRoot.get("actInvalidation")), 1)
.otherwise(0).as(Integer.class);
Expression<?> actInvalidationPath = actRoot.get("actInvalidation");
Order byInvalidationOrder = builder.asc(actInvalidationPath);
Path<Date> publicationDate = actRoot.get("metadata").get("publicationDate");
Order byLastModificationDate = builder.desc(publicationDate);
Order byTest = builder.asc(test);
query.select(act).orderBy(byTest, byInvalidationOrder, byLastModificationDate);
entityManager.createQuery(query).getResultList();
If i have row keys like
a_c
b_c
j_f
f_d
d_c
I should get all the rows matching _c. How to set start and stop row key here . I am trying to get the scan result out of start and stop row key and not with rowfilter or other filter types.
You can write your own filter function if you don't want to use RowFilter. But I suggest you to use PrefixFilter if you can't write your own filter function and don't want to use RowFilter
Example for Java:
byte[] prefixF= Bytes.toBytes("_c");
Scan scan = new Scan(prefixF));
PrefixFilter prefixFilter = new PrefixFilter(prefixF);
scan.addFilter(prefixFilter);
ResultScanner resultScanner = table.getScanner(scan);
Above code is equal to hbase> scan 'YourTablename', { FILTER => "PrefixFilter('_c')"}
You can use Hbase STARTROW and ENDROW filter. It basically scans data between the rowkey range (ENDROW excluded).
scan 'table_name', {STARTROW=>"<start_row_key>", ENDROW=>"<end_row_key>"}
I have a Hbase Table with the following description.
For a row key, my column would be of the form a_1, a_2,a_3,b_1,c_1,C_2 and so on, a compound key format.
Suppose one of my row is of the form
row key - row1
column family - c1
columns - a_1, a_2,a_3,b_1,b_2,c_1,C_2,d_9,d_99
Can I, by any operation retrieve a,b,c,d as the columns corresponding to row1, I am not bothered about whatever be the suffixes for a,b,c...
I can get all column names for a given row, add them to set by splitting the row keys by their first part and emit the set. I am worried, if there would be a better way of doing it by filters or some other hbase way of getting it done, please comment...
You can use COlumnPrefixFilter for that. You can see the following code
Configuration hadoopConf = new Configuration();
hadoopConf.set("hbase.zookeeper.quorum", "localhost");
hadoopConf.set("hbase.zookeeper.property.clientPort", "2181");
HTable hTable = new HTable(hadoopConf, "KunderaExamples");
Scan scan = new Scan();
scan.setFilter(new ColumnPrefixFilter("A".getBytes()));
ResultScanner scanner = hTable.getScanner(scan);
Iterator<Result> resultsIter = scanner.iterator();
while (resultsIter.hasNext())
{
Result result = resultsIter.next();
List<KeyValue> values = result.list();
for (KeyValue value : values)
{
System.out.println(value.getKey());
System.out.println(new String(value.getQualifier()));
System.out.println(value.getValue());
}
}