how to do Gremlin contain search for both number and string - node.js

Neptune 1.0.2.1 + Gremlin + nodejs.
I have a vertext and property, e.g. Vertex - Device, property - Test, the Test property could store different type of data, e.g. number and string
Vertex 1 - Test = ['ABCD','xyz']
Vertex 2 - Test = [123,'XYZ']
I want to do a 'containing' search, e.g. Test=A, or Test=123 regardless the datatype.
I was trying
queryText = 'BC' //this throw error
or queryText = 123 //this actually works
//I expect both case should hit the result.
g.V().hasLabel('Device').or(__.has('Test', parseFloat(queryText)), __.has('Test', textP.containing(queryText)));
but get 'InternalFailureException\' error
Is it possible I can write a single query regardless the datatype?
if not possible, or at least make textP.containing work with multiple query assuming I know the datatype? right now the containing search throw error if the property contains number

It looks like you have the closing bracket in the wrong place inside the or() step. You need to close the first has step before the comma.
In your example
g.V().hasLabel('Device').or(__.has('Test', parseFloat(queryText), __.has('Test', textP.containing(queryText))));
Which should be
g.V().hasLabel('Device').or(__.has('Test', parseFloat(queryText)), __.has('Test', textP.containing(queryText)));
EDITED and UPDATED
With the corrected query and additional clarification about the data model containing different types for the same property key, I was able to reproduce what you are seeing. However, the same behavior can be seen using TinkerGraph as well as Neptune. The error message generated is is a little different but the meaning is the same. Given the fact that TinkerGraph behaves the same way I am of the opinion that Neptune is behaving consistently with the "reference" implementation. That said, this raises a question as to whether the TextP predicates should be smarter and check the type of the property before attempting the test.
gremlin> graph = TinkerGraph.open()
==>tinkergraph[vertices:0 edges:0]
gremlin> g = graph.traversal()
==>graphtraversalsource[tinkergraph[vertices:0 edges:0], standard]
gremlin> g.addV('test').property('x',12.5)
==>v[0]
gremlin> g.addV('test').property('x','ABCDEF')
==>v[2]
gremlin> g.V().hasLabel('test').or(has('x',12.3),has('x',TextP.containing('CDE')))
java.math.BigDecimal cannot be cast to java.lang.String
Type ':help' or ':h' for help.
Display stack trace? [yN]
ADDITIONAL UPDATE
I created a Jira issue so the Apache TinkerPop community can consider making a change to the TextP predicates.
https://issues.apache.org/jira/browse/TINKERPOP-2375

Related

flux query: filter out all records related to one matching the condition

I'm trying to filter an influx DB query (using the nodeJS influxdb-client library).
As far as I can tell, it only works with "flux" queries.
I would like to filter out all records that share a specific attribute with any record that matches a particular condition. I'm filtering using the filter-function, but I'm not sure how I can continue from there. Is this possible in a single query?
My filter looks something like this:
|> filter(fn:(r) => r["_value"] == 1 and r["button"] == "1" ) and I would like to leave out all the record that have the same r["session"] as any that match this filter.
Do I need two queries; one to get those r["session"]s and one to filter on those, or is it possible in one?
Update:
Trying the two-step process. Got the list of r["session"]s into an array, and attempting to use the contains() flux function now to filter values included in that array called sessionsExclude.
Flux query section:
|> filter(fn:(r) => contains(value: r["session"], set: ${sessionsExclude}))
Getting an error unexpected token for property key: INT ("102")'. Not sure why. Looks like flux tries to turn the values into Integers? The r["session"] is also a String (and the example in the docs also uses an array of Strings)...
Ended up doing it in two queries. Still confused about the Strings vs Integers, but casting the value as an Int and printing out the array of r["session"] within the query seems to work like this:
'|> filter(fn:(r) => not contains(value: int(v: r["session"]), set: [${sessionsExclude.join(",")}]))'
Added the "not" to exclude instead of retain the values matching the array...

How to get [a b] as my output when I pass a,b using values(a,b) in the same order?

I am using gremlin console to check my query working or not. I am able to get the required data but in the reverse order.
In the end of my query, I am using
values.('id','name').fold()
But the output I am getting is [name id].
How to get the output as [id name]?
Thank you.
Gremlin typically doesn't do anything to preserve order and relies on the order provided by the underlying graph database. If you need order then you need to specify the order in some way. I think that you could use union() for that:
gremlin> g = TinkerFactory.createModern().traversal()
==>graphtraversalsource[tinkergraph[vertices:6 edges:6], standard]
gremlin> g.V(1).union(values('name'),values('age')).fold()
==>[marko,29]
gremlin> g.V(1).union(values('age'),values('name')).fold()
==>[29,marko]
I'm not sure if it's a great idea to rely on union() though. Like TinkerGraph should respect the order specified there, but I'm not sure if other graphs will. Perhaps a better solution would be to explicit with order():
gremlin> g.V(1).properties('name','age').order().by(key).value()
==>29
==>marko
That's alphabetical sort by key though and not the order you typed them. Ultimately though if you're just validating results it would probably be better to just return a Map with project()
gremlin> g.V(1).project('name','age').by('name').by('age')
==>[name:marko,age:29]
gremlin> g.V(1).project('age','name').by('age').by('name')
==>[age:29,name:marko]
gremlin> g.V(1).project('age','name').by('age').by('name').next().getClass()
==>class java.util.LinkedHashMap
As you can see project() preserves order() as it uses a LinkedHashMap and executes the by() modulators in the order they are defined. What's neat about that is that you really wanted that List form you were asking about in your initial question you could then just grab the values from the Map:
gremlin> g.V(1).project('name','age').by('name').by('age').select(values)
==>[marko,29]
gremlin> g.V(1).project('age','name').by('age').by('name').select(values)
==>[29,marko]
Hopefully one of these approaches works for your situation.

gremlin outputs different from as seen on the internet, I think in bytes

How to get gremlin output normal indices along with v
Currently it outputs something like this
gremlin> g.V
WARN com.thinkaurelius.titan.graphdb.transaction.StandardTitanTx - Query requires iterating over all vertices [()]. For better performance, use indexes
gremlin> juno = g.addVertex(null);
==>v[128824]
gremlin> june = g.addVertex(null);
==>v[128828]
gremlin> jape = g.addVertex(null);
==>v[128832]
But as I saw on the internet it should be output something like this when a vertex is added in the graph
gremlin> g.V
WARN com.thinkaurelius.titan.graphdb.transaction.StandardTitanTx - Query requires iterating over all vertices [()]. For better performance, use indexes
gremlin> juno = g.addVertex(null);
==>v[1]
gremlin> june = g.addVertex(null);
==>v[2]
gremlin> jape = g.addVertex(null);
==>v[3]
The same problem occurs when I try to load about 10000 vertices. All these vertices have _id field in it but after loading this field is gone. It also not that the vertices have been loaded with this id....same is the case with _type field its also not present after loading.
I need these id and type because they map to something in other table too.
Here is a look at my rexter doghouse about the 3 loaded vertices
http://i.imgur.com/xly0jf8.png
So bit confused about all this stuff.
Thanks in advance
When vertices are added to Titan an Element identifier is assigned. That value is up to Titan and you should not expect it to start at "1" or any other specific number when you do. If you need there to be some kind of number like that you should add it yourself.
With respect to the _id and _type fields, I'm assuming that you are referring to fields found in JSON output from Rexster. Note that those are Rexster fields that are appended to the output. _id is always there and should map directly to Vertex.id() or Edge.id() depending on the data you are returning. _type just refers to the whether the JSON returned is representative of a "vertex" or an "edge". That data is not stored in Titan itself.

Subsonic : Same column name different tables

I have a query where I need to do a "Where" clause for two different columns in two different tables but subsonic creates the same parametrized parameter name for both which is causing an issue. How can I fix this?
string _RawSql = new Select()
.From(Tables.Table1)
.InnerJoin(Tables.Table2)
.InnerJoin(Table3.SidColumn, Table2.Table3SidColumn)
.Where(Table1.SidColumn).IsEqualTo(2)
.And(Table3.SidColumn).IsEqualTo(1)
.BuildSqlStatement();
The query this is creating is
SELECT ....
FROM [dbo].[Table1]
INNER JOIN [dbo].[Table2] ON [dbo].[Table1].[Table2Sid] = [dbo].[Table2].[Sid]
INNER JOIN [dbo].[Table3] ON [dbo].[Table2].[Table3Sid] = [dbo].[Table3].[Sid]
WHERE [dbo].[Table1].[Sid] = #Sid
AND [dbo].[Table3].[Sid] = #Sid
Note that in the last two lines its using #Sid for both Table1 and Table3. How go I do it so it uses #Sid0 and #Sid1?
Any help would be appreciated. Thanks
Thanks for the response, I really appreciate it. I am using 2.1
I am already using TableColumn. Below is the c# subsonic code...
.Where(Table1.SidColumn).IsEqualTo(2)
.And(Table3.SidColumn).IsEqualTo(1)
which creates the following sql when viewed in sql profiler
WHERE [dbo].[Table1].[Sid] = #Sid
AND [dbo].[Table3].[Sid] = #Sid
Could you please show me how can I replace these lines with the way you are suggesting? I would really rather not use literal "Table2.Sid = 2"
ranmore, the issue is same with variables or with constants.
I have even tried
.Where("Table1.Sid").IsEqualTo(2)
.And("Table3.Sid").IsEqualTo(1)
This creates the query as
WHERE Table1.Sid = #Table1.Sid0
AND Table3.Sid = #Table3.Sid1
I finally get different parametrized vars in this case but now SQL Server complains because it does not like . in the parametrized var names.
I have no clue how to perform a join with 2 where clauses for 2 different tables!
What version are you using? In 2.2 You can use the TableColumn object to get around this (it may be the same for 2.1 as well. So instead of using the struct, as you're doing, you can use the object (Table2.SidColumn).
If push comes to shove - you can override everything with a string - so in your case you could use "Table1.Sid" and "Table2.Sid" right in the Where() method.
I haven't been able to confirm this, but perhaps the problem only happens with literals? (not sure if your sample code is like that for brevity's sake)
int table1SidColumnValue = 2;
int table3SidColumnValue = 1;
.Where(Table1.SidColumn).IsEqualTo(table1SidColumnValue)
.And(Table3.SidColumn).IsEqualTo(table2SidColumnValue)
I remember seeing a problem with this when using multiple .In() clauses with literal values, not sure if that applies to your problem though.
I'm not sure what version of the code I have but your query produces numbered parameters for me.
If you look at Line 255 of ANSISqlGenerator.cs
https://github.com/subsonic/SubSonic-2.0/blob/master/SubSonic/SqlQuery/SqlGenerators/ANSISqlGenerator.cs
c.ParameterName = String.Concat(col.ParameterName, query.Constraints.IndexOf(c));
The where parameters really should have numbers appended to them... maybe pull the latest version?

Subsonic - Bit operation in Where Clause

I'm trying to make something like this:
int count = new Select().From(tblSchema).Where("Type & 1").IsEqualTo("1").GetRecordCount();
And the error message is:
Incorrect syntax near '&'.
Must declare the scalar variable "#Deleted".
Is it possible to do that with SubSonic?
Must declare the scalar variable
"#Deleted"
The second error would be caused by using logical deletes on the table you are querying (the table has an isDeleted or Deleted column).
But I'm looking through the code, I'm not sure how that parameter is getting in there. The SqlQuery.GetRecordCount method doesn't call CheckLogicalDelete(), from what I can tell. Is that error message unrelated?
This seems to be a bug in the way SubSonic is naming it's parameters when it generates the SQL to be executed.
What's happening is that SubSonic is looking at "Type & 1" and then creating a parameter to compare against called #Type&10 which is not a valid SQL parameter name. So you'll end up with the following SQL from your original query. You should submit a bug to http://code.google.com/p/subsonicproject/
Meanwhile you can workaround the bug for now by using an inline query:
http://subsonicproject.com/docs/Inline_Query_Tool
It is a little fuzzy as to what you are trying to accomplish but here is a best guess.
int count = new Select().From(tbl.Schema).Where(tbl.TypeColumn).IsEqualTo(true).GetRecordCount();

Resources