HBase FuzzyRowFilter doesn't work - filter

I have a row key composed of twenty characters like this:
XXAAAAXXXXXXXXXXXXXXX
I want to scan using a FuzzyRowFilter on the AA value on 2 to 6 position . But AA is not fixed value.

If you don't have AAAA as fixed,you can do like this :
FilterList filterList = new FilterList(FilterList.Operator.MUST_PASS_ONE);
String[] matches=new String[]{"AAAA","BBBB"};
for (String match:matches) {
byte[] rk = Bytes.toBytesBinary("??" + match + "??????????????");
byte[] fuzzyVal = new byte[]{1, 1, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1};
List<Pair<byte[], byte[]>> pairs = new ArrayList<>();
pairs.add(new Pair<>(rk, fuzzyVal));
filterList.addFilter(new FuzzyRowFilter(pairs));
}
Scan scan=new Scan();
scan.setFilter(filterList);
This will filter based on all the fuzzyFilters in the list and match based on FilterList.Operator.MUST_PASS_ONE.
Based on your requirements,go ahead and modify it accordingly.

Sorry but using,
FilterList filterList = new FilterList(/*FilterList.Operator.MUST_PASS_ONE*/);
String[] matches=new String[]{"1609","1610"};
for (String match:matches) {
byte[] rk = Bytes.toBytesBinary("??" + match + "??????????????");
byte[] fuzzyVal = new byte[]{1, 1, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1};
List<Pair<byte[], byte[]>> pairs = new ArrayList<>();
pairs.add(new Pair<>(rk, fuzzyVal));
filterList.addFilter(new FuzzyRowFilter(pairs));
}
Scan scan_fuzzy=new Scan();
scan_fuzzy.setFilter(filterList);
ResultScanner rs_fuzzy = table.getScanner(scan);
for( Result result : rs_fuzzy) {
System.out.println(result);
System.out.println("Value: " + Bytes.toString(result.getValue(FAMILY,COLUMN)));
}
my result doesn't contain just the row corresponding to the rowkey :02160901222720647002
but all the row (and the rowkey) of my table

Related

how to group by columnA and sum columnB, columnC in mixpanel JQL

I have a JQL in mixpanel. I managed to get to a result in the following format:
key, count1, count2, count3
a , 10, 0, 0
a , 0, 3, 0
a , 0, 0, 7
b , 2, 0, 0
b , 0, 3, 0
b , 0, 0, 5
And I'd like to get the results like:
key, count1, count2, count3
a , 10, 3, 7
b , 2, 3, 5
In other words: groupBy(['key'], WHAT_REDUCER_DO_I_NEED???)
You can use multiple reducers in your groupBy statement like this
.groupBy(['key'], [
mixpanel.reducer.sum('count1'),
mixpanel.reducer.sum('count2'),
mixpanel.reducer.sum('count3')
])
.groupBy(["key"], function(accumulators, events){
var sum = {"count1":0,"count2":0,"count3":0};
for (var i = 0; i < accumulators.length; ++i) {
sum["count1"] += accumulators[i]["count1"];
sum["count2"] += accumulators[i]["count2"];
sum["count3"] += accumulators[i]["count3"];
}
for (i = 0; i < events.length; ++i) {
var event = events[i];
sum["count1"] += event["count1"];
sum["count2"] += event["count2"];
sum["count3"] += event["count3"];
}
return sum;
})

Linq: Select 1st item from other group

I am trying to write a query to find just one item from the group, where they grouped by Industry and Weight, then from this one I have to get where Weight is Max and Balance is Max too
This is the example:
var data = new[] {
new {ID = 1, Industry = 2, Weight = 2, Balance = 500},
new {ID = 2, Industry = 2, Weight = 2, Balance = 300},
new {ID = 3, Industry = 2, Weight = 1, Balance = 100},
new {ID = 5, Industry = 4, Weight = 1, Balance = 100},
new {ID = 6, Industry = 4, Weight = 2, Balance = 150},
new {ID = 7, Industry = 4, Weight = 1, Balance = 300},
};
var res = from a in data group a by new {a.Industry, a.Weight} into g
let ID = g.First().ID
let Balance = g.Max(a => a.Balance)
select new { ID, g.Key.Industry, g.Key.Weight, Balance};
Console.WriteLine(res);
So as the result I should get just two records
ID Industry Weight Balance
1 2 2 500
6 4 2 150
but with query above I got 4 records
Any advice?
Regards,
Dmitriy
There are probably many different solutions, but one would be to only group by Industry and sort each group according to your "first element to pick" criteria and then pick the first item in each group.
var res = from item in data
group item by item.Industry into g
let first = g.OrderByDescending(x => x.Weight)
.ThenByDescending(x => x.Balance).First()
select first;
data.GroupBy(x=>new {x.Industry,x.Weight})
.ToDictionary(y=>y.Key,y=>y.ToList().Max(x=>x.Balance));
If you dont want a dictionary then you can as well Select a new DTO or a dynamic object as follows:
data.GroupBy(x=>new {x.Industry,x.Weight})
.Select(x=>new {x.Key.Industry,x.Key.Weight,x.ToList().Max(y=>y.Balance)});
Hopefully that is what you need.

Dynamic linq - Group by interval (DateTime, Numeric)

I search everywhere and didn`t find anwser for this question. I want to group by intervals (DateTime, Numeric) in Dynamic linq (the data will be crated dynamically so i must use dynamic linq)
Lets assume that we have such data:
ID|Date|Price
1|2010-11-01|100
2|2010-11-01|120
3|2010-11-02|50
4|2010-12-01|30
5|2010-12-01|220
6|2011-01-01|400
How to get this data grouped by like this
-(Group by Day) following groups
->2010-11-01 = 2 elements
->2010-11-02 = 1 elements
->2010-12-01 = 2 elements
->2011-01-01 = 1 elements
-(Group by Month) following groups
->2010-11 = 3 elements
->2010-12 = 2 elements
->2011-01 = 1 elements
-(Group by Quarter) following groups
->2010 q.03 = 5 elements
->2011 q.01 = 1 elements
-(Group by Year) following groups
->2010 = 5 elements
->2011 = 1 element
-(Group by Price (From 0, Each 50)) following groups
-> <0-50) = 1 elements
-> <50-100) = 1 elements
-> <100-150) = 2 elements
-> <200-250) = 1 elements
-> <400-450) = 1 elements
-(ideally it would be Group by Price (From 0-50,From 50-150, From 150-500)) following groups
-> <0-50) = 1 elements
-> <50-150) = 3 elements
-> <150-500) = 2 elements
Any Ideas? I stress again - it must be DYNAMIC LINQ or eventually some sophisticated lambda expression? I should been able to "group" it by column name that will be in string. e.g.
GroupBy("Date"), GroupBy("Price");
Here's how to do it:
For instance:
Group by Month
public Item[] data =
{
new Item { Date = new DateTime(2011, 11, 6), Price = 103, Name = "a" },
new Item { Date = new DateTime(2011, 11, 16), Price = 110, Name = "b" },
new Item { Date = new DateTime(2011, 12, 4), Price = 200, Name = "c" },
new Item { Date = new DateTime(2011, 12, 4), Price = 230, Name = "d" },
new Item { Date = new DateTime(2012, 1, 15), Price = 117, Name = "e" }
};
var groups = data.AsQueryable().GroupBy("Date.Month", "it").Cast<IGrouping<int, Item>>();
You can use "Date.Day" and "Date.Year" and for something like a price range you could use a function which maps everything in the range onto the same value e.g. using integer division "(it.Price / 50)"

Linq group by + where for each group

I want to write a linq expression that will return the ID that does not contain a particular value. For example, I want to return all distinct IDs that do not have Value = 30.
ID, Value
1, 10
1, 20
1, 30
2, 10
2, 20
3, 10
3, 20
The result should be 2 and 3 since non of these have a Value with 30.
Is this possible to do with a single expression?
Thanks
Sure, this will do it:
var query = from i in list
group i by i.GroupId into g
where g.Any(p => p.ItemId == 30) == false
select g.Key;
foreach(var result in query) { Console.WriteLine(result); }
This outputs:
2
3
Here I have used, as an example:
class Product {
public int GroupId { get; set; }
public int ItemId { get; set; }
}
and
var list = new List<Product>() {
new Product() {GroupId = 1, ItemId = 10},
new Product() {GroupId = 1, ItemId = 20},
new Product() {GroupId = 1, ItemId = 30},
new Product() {GroupId = 2, ItemId = 10},
new Product() {GroupId = 2, ItemId = 20},
new Product() {GroupId = 3, ItemId = 10},
new Product() {GroupId = 3, ItemId = 20},
};
I don't have Linq, but here is the SQL Server SQL to do what you want:
DECLARE #YourTable table (ID int, value int)
insert into #YourTable VALUES (1, 10)
insert into #YourTable VALUES (1, 20)
insert into #YourTable VALUES (1, 30)
insert into #YourTable VALUES (2, 10)
insert into #YourTable VALUES (2, 20)
insert into #YourTable VALUES (3, 10)
insert into #YourTable VALUES (3, 20)
SELECT DISTINCT ID
FROM #YourTable y1
WHERE NOT EXISTS (SELECT Value
FROM #YourTable y2
WHERE y1.ID=y2.id and y2.value=30)
OUTPUT:
ID
-----------
2
3
(2 row(s) affected)

ISO 9797-1 Algorithm 1 [CBC-MAC] in C#

It seems that there're 6 variations to CBC-MAC algorithm. I've been trying to match the MAC algorithm on the PINPad 1000SE [which per manual is ISO 9797-1 Algorithm 1].
I got an excellent start from here.
And I coded the algorithm as below:
public static byte[] CalculateMAC(this IPinPad pinpad, byte[] message, byte[] key)
{
//Divide the key with Key1[ first 64 bits] and key2 [last 64 bits]
var key1 = new byte[8];
Array.Copy(key, 0, key1, 0, 8);
var key2 = new byte[8];
Array.Copy(key, 8, key2, 0, 8); //64 bits
//divide the message into 8 bytes blocks
//pad the last block with "80" and "00","00","00" until it reaches 8 bytes
//if the message already can be divided by 8, then add
//another block "80 00 00 00 00 00 00 00"
Action<byte[], int> prepArray = (bArr, offset) =>
{
bArr[offset] = 0; //80
for (var i = offset + 1; i < bArr.Length; i++)
bArr[i] = 0;
};
var length = message.Length;
var mod = length > 8? length % 8: length - 8;
var newLength = length + ((mod < 0) ? -mod : (mod > 0) ? 8 - mod : 0);
//var newLength = length + ((mod < 0) ? -mod : (mod > 0) ? 8 - mod : 8);
Debug.Assert(newLength % 8 == 0);
var arr = new byte[newLength];
Array.Copy(message, 0, arr, 0, length);
//Encoding.ASCII.GetBytes(message, 0, length, arr, 0);
prepArray(arr, length);
//use initial vector {0,0,0,0,0,0,0,0}
var vector = new byte[] { 0, 0, 0, 0, 0, 0, 0, 0 };
//encrypt by DES CBC algorith with the first key KEY 1
var des = new DESCryptoServiceProvider { Mode = CipherMode.CBC };
var cryptor = des.CreateEncryptor(key1, vector);
var outputBuffer = new byte[arr.Length];
cryptor.TransformBlock(arr, 0, arr.Length, outputBuffer, 0);
//Decrypt the result by DES ECB with the second key KEY2 [Original suggestion]
//Now I'm Encrypting
var decOutputBuffer = new byte[outputBuffer.Length];
des.Mode = CipherMode.ECB;
var decryptor = des.CreateEncryptor(key2, vector);
//var decryptor = des.CreateDecryptor(key2, vector);
decryptor.TransformBlock(outputBuffer, 0, outputBuffer.Length, decOutputBuffer, 0);
//Encrypt the result by DES ECB with the first key KEY1
var finalOutputBuffer = new byte[decOutputBuffer.Length];
var cryptor2 = des.CreateEncryptor(key1, vector);
cryptor2.TransformBlock(decOutputBuffer, 0, decOutputBuffer.Length, finalOutputBuffer, 0);
//take the first 4 bytes as the MAC
var rval = new byte[4];
Array.Copy(finalOutputBuffer, 0, rval, 0, 4);
return rval;
}
Then I discovered there're 3 padding schemes and the one that gave me a start may not necessarily be right. The manual came to my rescue again. It seems the device only pads with 0s. Additional block is also nowhere mentioned so I made the below changes:
Action<byte[], int> prepArray = (bArr, offset) =>
{
bArr[offset] = 0; ... }
No additional block (if mod 0 [divisible by 8] do not change array length)
var newLength = length + ((mod < 0) ? -mod : (mod > 0) ? 8 - mod : 0);
The original suggestion wanted me to decrypt at the second step... but Valery here suggests that it's encrypt all the way. So I changed Decrypt to Encrypt. But still I'm unable to get the requisite MAC...
Manual says for key "6AC292FAA1315B4D8234B3A3D7D5933A" [since the key should be 16 bytes, I figured the key here's hex string so I took byte values of 6A, C2, 92, FA...
new byte[] { 106, 194, 146, ...] the MAC should be 7B,40,BA,95 [4 bytes] if the message is [0x1a + byte array of MENTERODOMETER]
Can someone help? Please?
Since Pinpad requires that the first character in message is a 0x1a...
public static byte[] CalculateAugmentedMAC(this IPinPad pinpad, string message, byte[] key)
{
var arr = new byte[message.Length + 1];
var source = Encoding.ASCII.GetBytes(message);
arr[0] = 0x1a; //ClearScreenIndicator
Array.Copy(source, 0, arr, 1, source.Length);
return CalculateMAC(pinpad, arr, key);
}
I'm calling the code above with this input:
var result = pad.CalculateAugmentedMAC("MENTERODOMETER", new byte[] { 106, 194, 146, 250, 161, 49, 91, 77, 130, 52, 179, 163, 215, 213, 147, 58 });
Most CBC MAC algorithms are implemented in BouncyCastle's JCE provider.
Look at: BouncyCastleProvider.java
You're probably looking for DESEDEISO9797ALG1MACWITHISO7816-4PADDING, which is an alias for DESEDEMAC64WITHISO7816-4PADDING, implemented here (well, it's a specific configuration of CBCBlockCipherMac using the DESedeEngine and ISO7816d4Padding, you'll have to jump between some classes to get the full picture):
JCEMac.java
Also, have a look at jPos:
JCESecurityModule.java
and their contributed retail MAC algorithm implementation:
retail-mac-contributed-by-vsalaman.zip
I am pretty sure (IIRC) that you need to call TransformFinalBlock at the end (per encryptor).
Can't answer to your specific terminal, but I use this to test MACs.
public static byte[] GenerateMAC(byte[] key, byte[] data)
{
using (MACTripleDES mac = new MACTripleDES(key))
return mac.ComputeHash(data);
}

Resources