Aerospike - Query with Multiple Filter parameters - lua

I'm trying to query aerospike using multiple filters taking reference from this link.
I am able to query aerospike based on the given lua script for 1 filter parameter but stuck up with lua script when have to pass more than 2 filter parameters (for example passing two more parameters like age, gender with password).
This is my first time with lua.
Lua Script:
local function map_profile(record)
return map {name=record.name, password=record.password}
end
function check_password(stream,password)
local function filter_password(record)
return record.password == password
end
return stream : filter(filter_password) : map(map_profile)
end
Thanks in advance.

The filter function can have extra parameters and return a closure which can both access those, while still conforming to the expected stub of one parameter being the record, with a boolean return value.
local function filter_password(password)
return function(rec)
if rec['password'] and (type(rec['password']) == 'string') and
rec['password'] == password then
return true
end
return false
end
end
local function map_profile(record)
return map {name=record.name, password=record.password}
end
function check_password(stream,password)
return stream : filter(filter_password(password)) : map(map_profile)
end
However, the best way to query or scan for multiple filters these days (ever since release 3.12) is to use predicate filtering. In the majority of cases (unless you need to compare the values of two of the record's bins to each other in some way) you would skip UDFs and use the PredExp class (in the Java client, or its equivalent in another). You'd get back only those records that matched the filter, regardless of how complex of an expression you built. See the examples in the Aerospike Java client, or the C, C# and Go clients.

We developed SQL wrapper for Aerospike, that builds LUA code from your SQL query. It might be helpful to you.

Related

NEO4J/Cypher: Use result as condition for new create

i want to create a new node based on a return result in cypher. I cant figure out how to use CASE here(I guess thats what i need?)
I shorted the code because the above part is not important. I get a true or false in "result" and want to use this information to create a new node.
......
RETURN ((sum(r.rooms)+_rooms)<=a.allocation and count(r)>0) as result
If true then:
CREATE (s:SOMETHING)
You should read up on the WITH clause. This is similar to RETURN, except it allows you to continue the query. It's used for cases like this, where you need to aggregate or project out or control what's in scope (only the variables you include in the WITH clause are kept in scope afterwards) and continue the query past it.
...
WITH ((sum(r.rooms)+_rooms)<=a.allocation and count(r)>0) as result
WHERE result
CREATE (s:SOMETHING)

PagedResultList .size() and .getTotalCount() return different values in grails gorm

I have the following code
PagedResultList res = myService.getPage(paginateParams, ...)
println res.size() // returns 2
println res.getTotalCount() // returns 1
getPage looks like:
def criteria = MyDomain.createCriteria()
criteria.list(max: paginateParams.max, offset: paginateParams.offset) { // max is 10, offset is 0, sortBy is updatedAt and sortOrder is desc
eq('org', org)
order(paginateParams.sortBy, paginateParams.sortOrder)
}
why do the two method return different values? The documentation doesn't explain the difference, but does mention that getTotalCount is for number of records
currently on grails 2.4.5
edits:
println on res prints out:
res: [
com.<hidden>.MyDomain: 41679f98-a7c5-4193-bba8-601725007c1a,
com.<hidden>.MyDomain: 41679f98-a7c5-4193-bba8-601725007c1a]
Yes, res has a SINGLE object twice - that's the bug I'm trying to fix. How do I know that? I have an primary key on MyDomain's ID, and when I inspect the database, it's also showing one record for this particular org (see my criteria)
edit 2: I found this comment (http://docs.grails.org/2.4.5/ref/Domain%20Classes/createCriteria.html)
listDistinct If subqueries or associations are used, one may end up
with the same row multiple times in the result set. In Hibernate one
would do a "CriteriaSpecification.DISTINCT_ROOT_ENTITY". In Grails one
can do it by just using this method.
Which, if I understand correctly, is their way of saying "list" method doesn't work in this scenario, use listDistinct instead but then they go on to warn:
The listDistinct() method does not work well with the pagination
options maxResult and firstResult. If you need distinct results with
pagination, we currently recommend that you use HQL. You can find out
more information from this blog post.
However, the blog post is a dead link.
Related: GORM createCriteria and list do not return the same results : what can I do?
Not related to actual problem after question edited but this quote seems useful
Generally PagedResultList .size() perform size() on resultList property (in-memory object represent database record), while .getTotalCount() do count query against database. If this two value didn't match your list may contain duplicate.
After viewing related issues (GORM createCriteria and list do not return the same results : what can I do?) I determined that there were several approaches:
Use grails projection groupBy('id') - doesn't work b/c i need the entire object
USe HSQL - Domain.executeQuery - actually this didn't work for my scenario very well because this returns a list, whereas criteria.list returns a PagedResultList from which I previously got totalCount. This solution had me learning HSQL and also made me break up my existing logic into two components - one that returned PagedResultList and one that didn't
Simply keep a set of IDs as I process my PagedResultList and make sure that I didn't have any duplicates.
I ended up going with option 3 because it was quick, didn't require me to learn a new language (HSQL) and I felt that I could easily write the code to do it and I'm not limited by the CPU to do such a unique ID check.

passing collections as parameters with neo4j

I have been using parameters to query node indexes as such (using the rest api in java)-
final QueryResult<Map<String,Object>> result = engine.query("start nd=node:name_index(name={src}) return nd.age as age", MapUtil.map("src", "Susan");
However I haven't been able to get this to work for a collection of nodes/names. I have been trying something along the lines of-
final QueryResult<Map<String,Object>> result = engine.query("start nd=node:name_index(name={src}) return nd.age as age", MapUtil.map("src", Arrays.asList("Susan","Brian", "Ian"));
But it refuses to compile. I as wondering if there is something wrong in my syntax or that parameters are not designed to work in this context.
The name= syntax in the start is meant to do an index lookup on a property. It won't do an IN lookup. The way you can do this sort of lookup is like this (note it depends on Apache's StringUtils):
List<String> names = Arrays.asList("Susan","Brian", "Ian");
String luceneQuery = "name:("+StringUtils.join(names, ",")+")";
engine.query("start nd=node:name_index({luceneQuery}) return nd.age as age", MapUtil.map("luceneQuery", luceneQuery));
Just a note, this is the "legacy" index way of doing things. In 2.0 they've introduced label-based indexes, which work entirely differently.
Thanks a lot; though it would still only return a non empty answer when I added a space after the comma in line 2. I used-
String luceneQuery = "name:("+StringUtils.join(names, ", ")+")";
and it returned the age of one person. When I tried this:
String luceneQuery = "fs:(fs:"+ StringUtils.join(names, " OR fs:")+")";
it gave me all three ages. However, I am still unsure about whether this query will be able to leverage the usual advantages of parameters , i.e. will the engine be able to reuse the query and execution path the next time around (this time we may want to query for 4 names instead of 3)

Way to deep traverse a Groovy object with dot in string using GPath

The situation I have is that I'm querying MongoDB with a string for a field that is more than one level deep in the object hierarchy. This query must be a string. So for example I'm querying for something like this in Groovy:
def queryField = 'a.b.c' //this is variable and can be different every time
def result = mongodb.collection.findOne([queryField:5])
The problem no arises that in the result I want to find the value of the nested field. With GPath I could go one level deep and get a's value doing this
def aObj = result."a" //or result["a"]
However I want to go deeper than that by doing something like this:
def queryField = "a.b.c" //this can change every time and is not always 'a.b.c'
def cObj = result[queryField] //since field is variable, can't just assume result.a.b.c
This does not work in Groovy right now. There is a bug logged here, but I was wondering if there is a better work around to use for this scenario that is a bit cleaner than me parsing the string by splitting on the dot and then building the object traversal. Note that "a.b.c" is variable and unknown at runtime (e.g. it could be "a.b.d").
Based on the bug/thread it would appear there are some ambiguity problems with supporting a dotted property accessor. Based on the mailing list thread it would seem that evaluating the queryField string would be your best bet:
def result = [a: [b: [c: 42]]]
def queryString = 'a.b.c'
def evalResult = Eval.x(result, 'x.' + queryString)
assert evalResult == 42
Script on Groovy Web Console
The mailing list thread is a little old, so there's a new-ish (since at least 1.7.2) Eval class that can help out with running small snippets that don't have a large binding.
Otherwise, you can split the string and recursively do property evaluations on the object, effectively reproducing a subset of GPath traversal behavior.

Can Lua support case-insensitive method calls?

I'm using Lua as a data description language for my C++ app. I have a bunch of C++ classes bound to Lua using SLB 2.0. I have methods bound such as 'SetPos' or 'SetName'. I specify the position or name (for example) using a table with values keyed as 'pos' or 'name'. I want to be able to take the key, prepend 'set', and call the method, if it exists (it may not). Is that possible? If so, any suggestions?
I know I could make my bound methods lower case, but I'd rather keep them the same as the methods they're bound to (that may be my fallback though). I could try to build the method name based on my naming standards, but case insensitivity is less error prone.
I feel there should be a tricky piece of Lua that could solve this using metatables, but I haven't been able to work it out myself.
Any suggestions?
Thanks!
Case insensitivity is not really something Lua handles. All table lookups and local variable accesses are ultimately case sensitive string compares.
The best solution would be to just accept that you're dealing with a case sensitive system, just like C++, and deal with it.
However, if you really want to, you can do this. The simplest way would be to put every possible case permutation of a name in your function table. So your function table would have this:
["setname"] = theFunction,
["Setname"] = theFunction,
["sEtname"] = theFunction,
["SEtname"] = theFunction,
...
You can of course automate this with a function that takes each name in the table and replicates its data based on the case permutations.
A more involved but easier to use mechanism would be to use the __index and __newindex metamethods along with the empty table trick.
function CreateCaseInsensitiveTable()
local metatbl = {}
function metatbl.__index(table, key)
if(type(key) == "string") then
key = key:lower()
end
return rawget(table, key)
end
function metatbl.__newindex(table, key, value)
if(type(key) == "string") then
key = key:lower()
end
rawset(table, key, value)
end
local ret = {}
setmetatable(ret, metatbl)
return ret
end
Instead of creating a table with {}, you create the table with this function call. The table should otherwise function as normal (though obviously member access will be slightly slower).

Resources