I can't figure out how to rewrite my Cypher script in Gremlin.
First we used the .Net Neo4j client to connect to our Neo4j database and run Cypher queries on it. Then we decided to add an abstraction layer and connect to a Gremlin server instead (which, for now, hosts the same Neo4j database). So now I need to translate our queries from Cypher to Gremlin and I am finding it rather difficult.
Here's one of them:
MATCH (pc:ProductCategory)-[:HasRootCategory]->(r:RootCategory)
WHERE NOT (:ProductCategory)-[]->(pc)
AND pc.Id = r.RootId
RETURN pc;
One of my failed attempts:
g.V().match(as("pc").out("HasRootCategory").as("r"),as("pc").in().has('label', 'ProductCategory').count().is(0))).select("pc", "r").where("pc.Id", eq("r.RootId")).select("pc")
I found an example on stackoverflow using this 'match(as' construct, but it must be depracated or something, because I'm getting an error. Also, not sure how to compare properties with different names on nodes with different labels (I'm sure the 'where' is wrong...)
Any help would be appreciated.
The following traversal should be equivalent:
g.V().hasLabel("ProductCategory").as("pc").
not(__.in().hasLabel("ProductCategory")).
out("HasRootCategory").as("r").
where("pc", eq("r")).
by("Id").
by("RootId").
select("pc")
Since you don't really need the r label, the query can be tweaked a bit:
g.V().hasLabel("ProductCategory").as("pc").
not(__.in().hasLabel("ProductCategory")).
filter(out("HasRootCategory").
where(eq("pc")).
by("Id").
by("RootId"))
Last thing to mention: If a ProductCategory vertex can be connected to another ProductCategory vertex by only one (or more) specific edge label, that can lead nowhere else, it would be better to do:
g.V().hasLabel("ProductCategory").as("pc").
not(inE("KnownLabelBetweenCategories")).
filter(out("HasRootCategory").
where(eq("pc")).
by("Id").
by("RootId"))
On a different note, match() is not deprecated. I guess you tried to run your traversal in Groovy and it just failed because you didn't use __.as() (as, among others, is a reserved keyword in Groovy).
Related
Following the question at Difference in performance between using VALUES keyword and using directly the URI in the query?, I learned that using a VALUES clause at the end of the query is not always equivalent in terms of performance and query optimization than using directly a URI instead of the variable in the query string.
Comment from Andy says "VALUES at the end is "like setting variables" but isn't the same. The optimizer tries to push the values in but that can't happen in all cases as it changes the semantics."
Can someone explain in which cases this can't happen? for which query structures, and why exactly? I need to understand in which situations this technique (that I happily used for years now) is not advisable.
Note that I am not fluent with SPARQL algebra, so please try using simple words :-)
(I know this is not specific to Jena or RDF4J but I tag the question with these 2 tags since I understood the optimization of this might be different depending on the framework used).
I've been working off of the tutorial pages but seem to have a fundamental disconnect in my thinking transitioning off of RDBMS systems. I'm using MarkLogic and handling this database interaction through the Java API focusing on the search access via POJO method outlines in the tutorial documentation.
My reference up to this point has come from here principally: http://developer.marklogic.com/learn/java/processing-search-results
My scenario is this:
I have a series of documents. We'll call them 'books' for simplicity. I'm writing these books into my DB like this:
jsonDocMgr.write("/" + book.getID() + "/",
new StringHandle(
"{name: \""+book.getID()+"\","+
"chaps: "+ book.getNumChaps()+","+
"pages: "+ book.getNumPages()+","+
"}"));
What I want is to execute the following type of operation:
-Query all documents with the name "book*" (as ID is represented by book0, book1, book2, etc)
where chaps > 3. For these documents only, I want to modify the number of pages by reducing by half.
In an RDBMS, I'd use something like jdbcTemplate and get a result set for me to iterate through. For each iteration I'd know I was working with a single record (aka a book), parse the field values from the result set, make a note of the ID, then update the DB accordingly.
With MarkLogic, I'm awash in a sea of different handlers and managers...none of which seems to follow the pattern of the ResultSet with a cursor abstraction. Ultimately I want to do a two-step operation of check the chapter count then update the page field for that specific URI.
What's the most common approach to this? It seems like the most basic of operations...
Try the high-level Java API and see if it works for you. Create a multi-statement transaction with a query by example, then use document operations.
At a lower level, the closest match to a ResultSet is the ResultSequence class. The examples at http://docs.marklogic.com/javadoc/xcc/overview-summary.html are pretty good. For updates the interaction model between Java and MarkLogic is a bit different from JDBC and SQL. There is no SELECT... FOR UPDATE syntax.
The most efficient low-level technique is to select and update in one XQuery transaction, something like a stored procedure. However this requires good knowledge of XQuery. The other low-level approach is to use an XCC multi-statement transaction, which requires a little less knowledge of XQuery.
A minor issue in your code ... you definately do NOT want to end your JSON docuement URIs with "/" as you do in your sample code. You should end them with the ".json" or some other extension or no extension but definately not "/" as that is treated specially in the server.
I'm trying to get a list of Change Requests that match certain conditions, some of these conditions are met by using functions like has_attr().
I would like to ask is it at all possible, I need for instance to use such function has_associated_task(cvtype="task") is it possible to do that?
For queries I'm using the following pattern:
http://ip[:port]/change/oslc/db/dbURI/role/User/cr?oslc_cm.query=change:cvtype="problem" and request_type="Change_Request" and has_associated_task(cvtype="task")&oslc_cm.properties=problem_synopsis
this does work without the function term but I would like to extend the search criteria further, is there any other way besides doing a predefined query in change? Is there somewhere a list of terms? like change:cvtype (I've tried to see this [http://www.ibm.com/xmlns/prod/rational/change/1.0/][1] but I got a "whoops" from the web server)
There are some ways you could solve this:
OSLC Resource Shapes - some OSLC providers associate shapes (like schemas) that describe what you can expect from an OSLC Query Capability.
There isn't a way in the simple query syntax to test for null (or not null), assuming you want to have some condition such as (cvtype="task" and linkedTask != NULL). To get around this you can simply query based on cvtype="task" and locally filter the results using tools such as XPath or Jena. Alternatively you can do is look for extensions to the tool you are working with to see if they provide any extensions to the query syntax to support your use case, I don't have this information off hand.
Are there any open source tools that can generate a natural language description of a given SQL query? If not, some general pointers would be appreciated.
I don't know much about NLP, so I am not sure how difficult this is, although I saw from some previous discussion that the vice versa conversion is still an active area of research. It might help to say that the SQL tables I will be handling are not arbitrary in any sense, yet mine, which means that I know exact semantics of each table and its columns.
I can devise two approaches:
SQL was intended to be "legible" to non-technical people. A naïve and simpler way would be to perform a series of replacements right on the SQL query: "SELECT" -> "display"; "X=Y" -> "when the field X equals to value Y"... in this approach, using functions may be problematic.
Use a SQL parser and use a series of templates to realize the parsed structure in a textual form: "(SELECT (SUM(X)) (FROM (Y)))" -> "(display (the summation of (X)) (in the table (Y))"...
ANTLR has a grammar of SQL you can use: https://github.com/antlr/grammars-v4/blob/master/sqlite/SQLite.g4 and there are a couple SQL parsers:
http://www.sqlparser.com/sql-parser-java.php
https://github.com/facebook/presto/tree/master/presto-parser/src/main
http://db.apache.org/derby/
Parsing is a core process for executing a SQL query, check this for more information: https://decipherinfosys.wordpress.com/2007/04/19/parsing-of-sql-statements/
There is a new project (I am part of) called JustQuery.Me which intends to do just that with NLP and google's SyntaxNet. You can go to the https://github.com/justquery-me/justqueryme page for more info. Also, sign up for the mailing list at justqueryme-development#googlegroups.com and we will notify you when we have a proof of concept ready.
I'm using Hibernate for ORM of my Java app to an Oracle database (not that the database vendor matters, we may switch to another database one day), and I want to retrieve objects from the database according to user-provided strings. For example, when searching for people, if the user is looking for people who live in 'fran', I want to be able to give her people in San Francisco.
SQL is not my strong suit, and I prefer Hibernate's Criteria building code to hard-coded strings as it is. Can anyone point me in the right direction about how to do this in code, and if impossible, how the hard-coded SQL should look like?
Thanks,
Yuval =8-)
For the simple case you describe, look at Restrictions.ilike(), which does a case-insensitive search.
Criteria crit = session.createCriteria(Person.class);
crit.add(Restrictions.ilike('town', '%fran%');
List results = crit.list();
Criteria crit = session.createCriteria(Person.class);
crit.add(Restrictions.ilike('town', 'fran', MatchMode.ANYWHERE);
List results = crit.list();
If you use Spring's HibernateTemplate to interact with Hibernate, here is how you would do a case insensitive search on a user's email address:
getHibernateTemplate().find("from User where upper(email)=?", emailAddr.toUpperCase());
You also do not have to put in the '%' wildcards. You can pass MatchMode (docs for previous releases here) in to tell the search how to behave. START, ANYWHERE, EXACT, and END matches are the options.
The usual approach to ignoring case is to convert both the database values and the input value to upper or lower case - the resultant sql would have something like
select f.name from f where TO_UPPER(f.name) like '%FRAN%'
In hibernate criteria restrictions.like(...).ignoreCase()
I'm more familiar with Nhibernate so the syntax might not be 100% accurate
for some more info see pro hibernate 3 extract and hibernate docs 15.2. Narrowing the result set
This can also be done using the criterion Example, in the org.hibernate.criterion package.
public List findLike(Object entity, MatchMode matchMode) {
Example example = Example.create(entity);
example.enableLike(matchMode);
example.ignoreCase();
return getSession().createCriteria(entity.getClass()).add(
example).list();
}
Just another way that I find useful to accomplish the above.
Since Hibernate 5.2 session.createCriteria is deprecated. Below is solution using JPA 2 CriteriaBuilder. It uses like and upper:
CriteriaBuilder builder = session.getCriteriaBuilder();
CriteriaQuery<Person> criteria = builder.createQuery(Person.class);
Root<Person> root = criteria.from(Person.class);
Expression<String> upper = builder.upper(root.get("town"));
criteria.where(builder.like(upper, "%FRAN%"));
session.createQuery(criteria.select(root)).getResultList();
Most default database collations are not case-sensitive, but in the SQL Server world it can be set at the instance, the database, and the column level.
You could look at using Compass a wrapper above lucene.
http://www.compass-project.org/
By adding a few annotations to your domain objects you get achieve this kind of thing.
Compass provides a simple API for working with Lucene. If you know how to use an ORM, then you will feel right at home with Compass with simple operations for save, and delete & query.
From the site itself.
"Building on top of Lucene, Compass simplifies common usage patterns of Lucene such as google-style search, index updates as well as more advanced concepts such as caching and index sharding (sub indexes). Compass also uses built in optimizations for concurrent commits and merges."
I have used this in the past and I find it great.