I'm just starting to learn Neo4j and I've just stumbled across some issue.
It looks like Neo4j is using strong typing without on the fly type conversion, i.e. RETURN '17' = 17 results in false and RETURN '10' > 5 results in syntax error.
It looks very strange to me for NoSQL and schema-less database to implement such a strict behavior. Even strong typed schema-based databases such as MySQL and Postgresql allows type conversions in statements. Is this an ideology behind Neo4j? If so why?
Github issue.
In Neo4j 2.1 there were type conversion functions added, like toInt and toFloat that take care of the conversion.
In 2.0.x you can use str(17) = str('17') in the other direction.
Neo4j itself is less strict on structural information. But more strict on values. I.e. the value you put into a property is returned exactly like that and you have to convert it to a different type yourself. Some of that stems from its Java history and was already loosened for cypher.
Related
I have a really long insert query with more than 40 fields (from an 'inherited' Foxpro database) processed using OleDb, that produces the exception 'Data type mismatch.' Is there any way to know which field of the query is producing this exception?
By now I'm using the force brute method of reducing the number of fields on the insert until I locate the buggy one, but I guess it must be a more straight way to found it...
There isn't really any shortcut beyond taking a guess at which 20 might be the problem, chopping out the other 20 and testing, and repeating that reductive process until you hit it.
Or alternatively looking at the table structure(s) in the DBF and making sure the field types match to the OleDB types you're using. The details of how .NET types are mapped to Visual FoxPro table field types is here.
If you have access to the Visual FoxPro IDE you could probably do that a lot quicker by knocking up a little program or even just doing it in the Command Window.
You are not telling us the language you use, so that we could possibly give a sample to handle it.
Basically what you would do is:
Get the structure,
Parse the insert statement and get values,
Compare data types.
It should be a short code to make this check.
I believe internally Cypher / Gremlin translate statement into corresponding Java method calls. Is there a way to trace what method calls in run?
For example, in Hibernate, we can specify "show sql" to see generated sql statement.
[Edit]
The reasonws I want to do that:
1. For Debugging purpose:
To find out why the cypher / gremlin doesn't produce the expected result.
For learning purpose:
To find what's happening under the hood
For optimization:
To find out where the bottleneck is.
In Cypher, that is planned for the coming months to add. Ultimately, yes, currently the methods used under the Hood are the Java Neo4j core API and the Traversal Framework. Mind adding a case that is causing you problem?
For Gremlin, do a .toString() at the end of your Gremlin expression to see which Pipes (http://pipes.tinkerpop.com) it ultimately compiles down to.
I'm already applying that and it works as if the integer value from the database is 0, the java boolean variable becomes false and vice versa. But I'm wondering if it's possible to have it the other way around to map 0 for true and 1 for false.
Which got me thinking, i've earlier mapped java enums to integers which is pretty well explained in the documentations and I'm wondering if Datanucleus is flexible enough to map any database type to any java type when either persisting the value or loading it. For example, to map database database below a specified value to java boolean false and exceeding that value to java boolean true. Or mapping strings to integers (string length may be).
Perhaps you just use standard JDO metadata and define the "jdbc-type" and see what happens. I wouldn't have thought its feasible to support every possible combination (and indeed many of them would be just plain daft).
We have an old application that reads in SQL text files and sends them to Sybase ASE 12.51. Our legacy app was written in Delphi 5 and is using the BDE TQuery component for this process and accessing Sybase with the BDE SQLinks for Sybase.
Pseudo code:
SQLText=readSQLFile;
aTQuery.SQL.add(SQLText);
aTQuery.ExecSQL;
Recently we moved our DB access layer to the Delphi XE ADO implementation - TADOQuery, using the Sybase supplied ADO provider, still using same model:
SQLText=readSQLFile;
aTADOQuery.SQL.add(SQLText)
aTADOQuery.ExecSQL;
After migrating to ADO, we discovered that certain data was missing. We traced the failure to this SQL construct:
Select myColumn from myTable
Where tranID = null
Knowing that this construct is sematically questionable at best, I did a 'double take' when I saw this code, but Sybase 12.5 accepts it - however using ADO, this segment fails.
We decided to change:
Where tranID = null
to
Where tranID is null
Then the missing data was loaded - problem solved, for this segment and several others as well.
Does anyone have an explanation for this behavior? Where/why did ADO apparently intercept and reject this seqment whereas the BDE passed it thru?
TIA
"NULL" has a very special meaning, and SQL needs a special handling. You can't compare a value to "NULL", that's why there is the special operator IS (NOT) NULL to check for it. An exhaustive explanation would take some space, here a simple explanation.
From a "mathematical" point of view, NULL can be thought as "infinity". You can't compare two infinite values easily, for example think about the set of integer numbers and even numbers. Both are infinite, but it seems logical the former is larger than the latter. All you can say IS both sets are infinite.
That's also helps to explain for example why 1 + NULL returns NULL and so on (usually only aggregate functions like SUM() ecc. may ignore NULL values - ignore, not turn NULLs into zeroes).
This metaphor may not hold true in sorting, because some databases choose to consider NULL less than any value (some kind of -infinity and thereby returning them first in ascending order), other the other way round. Some have an option to set where to return NULLs.
Check your database documentation about NULL arithmetics and NULL comparisons. field = NULL should have never been used, don't know if Sybase accepts it, but most SQL implementations don't, and I guess it is not SQL standards compliant. It is far better to get used to the IS (NOT) NULL syntax.
Update: Sybase has a "set ansinull" option, from the documentation (always RTFM!), in 12.5.1 it was expanded to disallow the '= NULL' syntax (when set to ON to make it compliant with SQL standards). When set to OFF '= NULL' works as 'IS NULL'.
Maybe the SQL Links or the ADO provider set it to one value or the other.
Can I convert Neo4J Database files to XML?
I agree, GraphML is the way to go, if you don't have problems with the verbosity of XML. A simple way to do it is to open the Neo4j graph from Gremlin, where GraphML is the default import/export format, something like
peters: ./gremlin.sh
gremlin> $_g := neo4j:open('/tmp/neo4j')
==>neograph[/tmp/neo4j, vertices:2, edges:1]
gremlin> g:save('graphml-export.xml')
As described here
Does that solve your problem?
With Blueprints, simply do:
Graph graph = new Neo4jGraph("/tmp/mygraph");
GraphMLWriter.outputGraph(graph, new FileOutputStream("mygraph.xml"));
Or, with Gremlin (which does the same thing in the back):
g = new Neo4jGraph('/tmp/mygraph');
g.saveGraphML('mygraph.xml');
Finally, to the constructor for Neo4jGraph, you can also pass in a GraphDatabaseService instance.
I don't believe anything exists out there for this, not as of few months ago when messing with it. From what I saw, there are 2 main roadblocks:
XML is hierarchical, you can't represent graph data readily in this format.
Lack of explicit IDs for nodes. Even though implicit IDs exist it'd be like using ROWID in oracle for import/export...not guaranteed to be the same.
Some people have suggested that GraphML would be the proper format for this, I'm inclined to agree. If you don't have graphical structures and you would be fine represented in an XML/hierarchical format...well then that's just bad luck. Since the majority of users who would tackle this sort of enhancement task are using data that wouldn't store that way, I don't see an XML solution coming out...more likely to see a format supporting all uses first.
Take a look at NoSqlUnit
It has tools for converting GraphML to neo4j and back again.
In particular, there is com.lordofthejars.nosqlunit.graph.parser.GraphMLWriter and com.lordofthejars.nosqlunit.graph.parser.GraphMLReader which read / write XML files to / from a neo4j database.