C#, GetByValue is not working

I am using C# and I am not able to get GetByValue working for me.

Following is my dictionary that I am storing as map:

Dictionary<string, string> { [“ot”] = “objectType”, [“oid”] = “objectId”, }

Following is my code to fetch the above map by value:

var dictionary = new Dictionary<string, string>
        {
            ["oid"] = "objectId"
        };      
        var mapRecord = await _asyncClient.Operate(null, CancellationToken.None, "key",
            MapOperation.GetByValue("n", Value.Get(dictionary) , MapReturnType.VALUE));

But I am not getting any result back. I am expecting all the values which have same objectId. I get all the values when I use Value.WILDCARD. But that’s not what I want.

This is how data is stored in db:

What am I missing here?

Let me understand your expectation. You have a nested map in bin “n”. (I am omitting string quotes below for brevity.)

bin “n” = { 123 : { oid:abc , k1:v1, k2:v2}, 345:{oid:cde, k1:v3, k2:v4}, 456 :{oid:abc , k1:v5, k2:v6}}

And, when you do GetByValue, you want to match to value oid:abc and get back, 123:{…} and 456:{…}?

Yes, your understanding is correct.

GetByValue in Maps is looking for exact match of all mapitems. It does not do partial match as you are trying to do. However, you can do wildcard match in lists. So you will have to change your data model slightly. See Java code example below and output. You can write the equivalent in C#.

int iAcct_id = 3;  //Acct_id = 1 to 1000.

ListOfLists ll = new ListOfLists();

Key user = new Key("test", "accts", iAcct_id); 
client.delete(null, user);
System.out.println( client.get(null, user) );

Map<Value, Value> m1 = new HashMap<Value, Value>();
m1.put(Value.get("id"), Value.get(123));
m1.put(Value.get("k1"), Value.get("v1"));
m1.put(Value.get("k2"), Value.get("v2"));
List<Value> inList = new ArrayList<Value>();
inList.add(Value.get("abc"));
inList.add(Value.MapValue.get(m1));           
ll.appendToList(client, user, inList);

m1.clear();
inList.clear();
m1.put(Value.get("id"), Value.get(345));
m1.put(Value.get("k1"), Value.get("v3"));
m1.put(Value.get("k2"), Value.get("v4"));
inList.add(Value.get("cde"));
inList.add(Value.MapValue.get(m1)); 
ll.appendToList(client, user, inList);
  
m1.clear();
inList.clear();
m1.put(Value.get("id"), Value.get(456));
m1.put(Value.get("k1"), Value.get("v5"));
m1.put(Value.get("k2"), Value.get("v6"));
inList.add(Value.get("abc"));
inList.add(Value.MapValue.get(m1));
ll.appendToList(client, user, inList);

m1.clear();
inList.clear();
m1.put(Value.get("id"), Value.get(789));
m1.put(Value.get("k1"), Value.get("v7"));
m1.put(Value.get("k2"), Value.get("v8"));
inList.add(Value.get("def"));
inList.add(Value.MapValue.get(m1));
ll.appendToList(client, user, inList);

System.out.println( client.get(null, user) );

List<Value> matchList = new ArrayList<Value>();
                matchList.add(Value.get("abc"));
                matchList.add(Value.WILDCARD);
   
System.out.println("Matching to this value: "+ matchList);   

Record rec = client.operate(null, user,
               ListOperation.getByValue("n",
                   Value.ListValue.get(matchList),                  
                   ListReturnType.VALUE));
                   
List<?> retList = (ArrayList<?>)rec.getList("n");   
int size = retList.size();
for(int i=0; i<size; i++){
  System.out.println(retList.get(i)); 
}

And the output:

null  <-- I start with a clean record.

(gen:4),(exp:395781083),(bins:(n:[[abc, {k1=v1, k2=v2, id=123}], [cde, {k1=v3, k2=v4, id=345}], [abc, {k1=v5, k2=v6, id=456}], [def, {k1=v7, k2=v8, id=789}]]))

Use the above List of Lists data model. First value is what you want to match. Next value is a map.  

Matching to this value: [abc, *]
[abc, {k1=v1, k2=v2, id=123}]
[abc, {k1=v5, k2=v6, id=456}]