This question already has answers here:
Neo4j Cypher: How to iterate over ExecutionResult result
(4 answers)
Closed 8 years ago.
String query1 = "START
a=node:node_auto_index(name=\"A\"),
m=node:node_auto_index(name=\"M\"),
b=node:node_auto_index(name=\"G\")
MATCH p=a-[*]-b-[*]-m " +
WHERE ALL(r in RELS(p) WHERE r.value >= 200) "
+ "WITH a, m, MIN(LENGTH(p)) AS l
MATCH p=a-[*]-b-[*]-m WHERE ALL(r
in RELS(p) WHERE r.value >= 200)" +
" AND LENGTH(p)=l RETURN p order by length(p) desc "; //limit 2
ExecutionResult eResult = exEngine.execute(query1);
I am using above query to get all paths between two nodes. how can I iterate over returning RelationShips.
I did it using following approach, the link posted above helped.
final Iterator rels = eResult.columnAs("p");
while (rels.hasNext()){
Path path = rels.next();
Iterable<Relationship> relationships = path.relationships();
java.util.Iterator<Relationship> relIterator = relationships.iterator();
while (relIterator.hasNext()){
Relationship rel = relIterator.next();
String aNode = (String) rel.getStartNode().getProperty("name");
String zNode = (String) rel.getEndNode().getProperty("name");
Long value = (Long) rel.getProperty("value");
System.out.println(aNode +" is connected to "+zNode + " with value "+value);
}
}
</code>
You can just return rels(p) as rels to just return the relationships. Or nodes(p) ftm.
If you are just interested in the names of the nodes of the path use extract.
return extract(n in nodes(p) : n.name) as names
Related
I'm trying to do a query to fin all possible paths that correspond to the pattern "(Order) - [ORDERS] -> (Product) - [PART_OF] -> (Category)" and would like to get the whole path (i.e. all 3 nodes and 2 relationships as their appropriate classes).
The method i used below only let me have 1 column of data (number of orders: 2155). If I tried it once more (the 2nd for loop), the number of row i'd get is 0(number of products: 0). Is there a way to save all the results as nodes and relationships or do I have to query the command 5 times over?
Please help!
String query = "MATCH (o:Order)-[:ORDERS]->(p:Product)-[:PART_OF]->(cate:Category) return o,p,cate";
try( Transaction tx = db.beginTx();
Result result = db.execute(query) ){
Iterator<Node> o_column = result.columnAs( "o" );
int i = 0;
for ( Node node : Iterators.asIterable( o_column ) )
{
i++;
}
System.out.println("number of orders: " + i);
i = 0;
Iterator<Node> p_column = result.columnAs( "p" );
for ( Node node : Iterators.asIterable( p_column ) )
{
i++;
}
System.out.println("number of products: " + i);
tx.success();
}
I've found a way to work around this in the code below, where i'd changes the return value to the node ID using id() then uses GraphDatabaseService.getNodeByID(long):
String query = "MATCH (o:Order)-[:ORDERS]->(p:Product)-[:PART_OF]->(cate:Category) return id(o), id(p), id(cate)";
int nodeID = Integer.parseInt(column.getValue().toString());
Node node = db.getNodeById(nodeID);
If you do this :
MATCH path=(o:Order)-[:ORDERS]->(p:Product)-[:PART_OF]->(cate:Category) return path
You can process path in your loop and unpack that. Takes a bit of exploring but all the information is in there.
Hope that helps.
Regards,
Tom
i am trying to fetch all the documents from a database without knowing the exact url's . I got one query
DocumentPage documents =docMgr.read();
while (documents.hasNext()) {
DocumentRecord document = documents.next();
System.out.println(document.getUri());
}
But i do not have specific urls , i want all the documents
The first step is to enable your uris lexicon on the database.
You could eval some XQuery and run cts:uris() (or server-side JS and run cts.uris()):
ServerEvaluationCall call = client.newServerEval()
.xquery("cts:uris()");
for ( EvalResult result : call.eval() ) {
String uri = result.getString();
System.out.println(uri);
}
Two drawbacks are: (1) you'd need a user with privileges and (2) there is no pagination.
If you have a small number of documents, you don't need pagination. But for a large number of documents pagination is recommended. Here's some code using the search API and pagination:
// do the next eight lines just once
String options =
"<options xmlns='http://marklogic.com/appservices/search'>" +
" <values name='uris'>" +
" <uri/>" +
" </values>" +
"</options>";
QueryOptionsManager optionsMgr = client.newServerConfigManager().newQueryOptionsManager();
optionsMgr.writeOptions("uriOptions", new StringHandle(options));
// run the following each time you need to list all uris
QueryManager queryMgr = client.newQueryManager();
long pageLength = 10000;
queryMgr.setPageLength(pageLength);
ValuesDefinition query = queryMgr.newValuesDefinition("uris", "uriOptions");
// the following "and" query just matches all documents
query.setQueryDefinition(new StructuredQueryBuilder().and());
int start = 1;
boolean hasMore = true;
Transaction transaction = client.openTransaction();
try {
while ( hasMore ) {
CountedDistinctValue[] uriValues =
queryMgr.values(query, new ValuesHandle(), start, transaction).getValues();
for (CountedDistinctValue uriValue : uriValues) {
String uri = uriValue.get("string", String.class);
//System.out.println(uri);
}
start += uriValues.length;
// this is the last page if uriValues is smaller than pageLength
hasMore = uriValues.length == pageLength;
}
} finally {
transaction.commit();
}
The transaction is only necessary if you need a guaranteed "snapshot" list isolated from adds/deletes happening concurrently with this process. Since it adds some overhead, feel free to remove it if you don't need such exactness.
find out the page length and in the queryMgr you can specify the starting point to access. Keep on increasing the starting point and loop through all the URL. I was able to fetch all URI. This could be not so good approach but works.
List<String> uriList = new ArrayList<>();
QueryManager queryMgr = client.newQueryManager();
StructuredQueryBuilder qb = new StructuredQueryBuilder();
StructuredQueryDefinition querydef = qb.and(qb.collection("xxxx"), qb.collection("whatever"), qb.collection("whatever"));//outputs 241152
SearchHandle results = queryMgr.search(querydef, new SearchHandle(), 10);
long pageLength = results.getPageLength();
long totalResults = results.getTotalResults();
System.out.println("Total Reuslts: " + totalResults);
long timesToLoop = totalResults / pageLength;
for (int i = 0; i < timesToLoop; i = (int) (i + pageLength)) {
System.out.println("Printing Results from: " + (i) + " to: " + (i + pageLength));
results = queryMgr.search(querydef, new SearchHandle(), i);
MatchDocumentSummary[] summaries = results.getMatchResults();//10 results because page length is 10
for (MatchDocumentSummary summary : summaries) {
// System.out.println("Extracted friom URI-> " + summary.getUri());
uriList.add(summary.getUri());
}
if (i >= 1000) {//number of URI to store/retreive. plus 10
break;
}
}
uriList= uriList.stream().distinct().collect(Collectors.toList());
return uriList;
Closed. This question needs details or clarity. It is not currently accepting answers.
Want to improve this question? Add details and clarify the problem by editing this post.
Closed 7 years ago.
Improve this question
I have the following complex data-structure:
Map<String, Map<String,String>> URL_and_entities = new HashMap<String, Map<String,String>>();
on the inside of a loop I finally want to populate it but I can't figure out how.
This is my code, it's essentially a series of nested loops that make an HTTP request to determine if they share a relationship, which is revealed by the presence (or absence) of a url. I'm trying to save the URL (if it exists), and the two entities that evoked it:
for (String entity_1 : Q_value_references_for_sentence_entities)
{
for (String entity_2 : Q_value_references_for_sentence_entities)
{
String URL_czech = "http://milenio.dcc.uchile.cl/sparql?default-graph-uri=&query=PREFIX+%3A+%3Chttp%3A%2F%2Fwww.wikidata.org%2Fentity%2F%3E%0D%0ASELECT+*+WHERE+%7B%0D%0A+++%3A"
+ entity_1 + "+%3FsimpleProperty+%3A"
+ entity_2 + "%0D%0A%7D%0D%0A&format=text%2Fhtml&timeout=0&debug=on";
URL wikidata_page = new URL(URL_czech);
HttpURLConnection wiki_connection = (HttpURLConnection)wikidata_page.openConnection();
InputStream wikiInputStream = null;
try
{
// try to connect and use the input stream
wiki_connection.connect();
wikiInputStream = wiki_connection.getInputStream();
}
catch(IOException error)
{
// failed, try using the error stream
wikiInputStream = wiki_connection.getErrorStream();
}
// parse the input stream using Jsoup
Document docx = Jsoup.parse(wikiInputStream, null, wikidata_page.getProtocol()+"://"+wikidata_page.getHost()+"/");
Elements link_text = docx.select("table.sparql > tbody > tr:nth-child(2) > td > a");
//link_text.text();
for (Element l : link_text)
{
String output = l.text();
output = output.substring(0, output.length()-1);
list_of_relation_URLs.add( output );
URL_and_entities.put( output , (entity_1, entity_2));
}
}
}
I'm not oppoed to using that crazy google library of wonky data-strucs, I've used it before, but in this case I can't see a compelling reason why it would be any better than Map<String, Map<String,String>>
Update
I'm having trouble getting the values out. This doesn't work it seems
String first__english_lang_Q = retrieved_entities.getKey();
String second_english_lang_Q = retrieved_entities.getValue();
System.out.println("`(" + value + ")'" + "`( " + entity_1 + ", " + entity_2 + ")'");
You just need a tuple, You can use the apache common Pair
Map<String, Pair<String,String>> URL_and_entities = new HashMap<String, Pair<String,String>>();
URL_and_entities.put("something", Pair.of("left", "right"))
URL_and_entities.get("something").getLeft();
URL_and_entities.get("something").getRight();
Try this:
Map<String,String> entities;
for (String entity_1 : Q_value_references_for_sentence_entities)
{
for (String entity_2 : Q_value_references_for_sentence_entities)
{
entities = new HashMap<String, String>();
entities.put(entity_1, entity_2);
...check that URL exist and doesn't return null, and then convert it to a String...
URL_and_entities.put(output, entities);
}
}
}
I don't understand though, why you are using a Map to store the two entities. Unless you plan on using one entity to reference the second entity, you can simply store the two entities in a simple array (or technically even an ArrayList or HashSet would be better than a Map).
Just do:
Map<String, String[]> URL_and_entities = new HashMap<String, String[]>();
String [] entities = new String[2];
for (String entity_1 : Q_value_references_for_sentence_entities)
{
for (String entity_2 : Q_value_references_for_sentence_entities)
{
entities[0] = entity_1;
entities[1] = entity_2;
...check that URL exist and doesn't return null, and then convert it to a String...
URL_and_entities.put(output, entities);
}
}
}
Then to retrieve and print all the values in the set you just do:
for (String url: byLetter.keySet()) {
String [] retrievedValues = URL_and_entities.get(url);
System.out.println(url + " " + retrievedValues[0] + ", " + retrievedValues[1];
}
If using an ArrayList do:
for (String url: byLetter.keySet()) {
ArrayList retrievedValues = URL_and_entities.get(url);
System.out.println(url + " " + retrievedValues.get(0) + ", " + retrievedValues.get(1);
}
I am able to get the iterations under the project object. Now how do I get the iteration I need under that project and then drill down to the stories in that iteration using the JAVA toolkit?
https://sandbox.rallydev.com/slm/webservice/v2.0/project/7191194697/iterations
Given a project:
String projectRef = "/project/1234";
You may scope your requests as follows:
iterationRequest.setProject(projectRef);
or
storyRequest.setProject(projectRef);
If you scoped a story request to a project, then you may query on stories by traversing Iteration.Name if you know the iteration already:
storyRequest.setQueryFilter(new QueryFilter("Iteration.Name", "=", "my Iteration 1"));
Here is a more complex example that returns stories assigned to iterations that fall within the timbox of a specific release. If, for example, you have 4 iterations per release, this code will return stories assigned to all four iterations.
If you code against the sandbox, replace the value in the host variable accordingly.
public class FindIterationsByReleaseDateAndStories {
public static void main(String[] args) throws URISyntaxException, IOException {
String host = "https://rally1.rallydev.com";
String username = "user#co.com";
String password = "secret";
String projectRef = "/project/12352608219";
String applicationName = "Find Iterations by Release Dates and Stories";
RallyRestApi restApi = null;
try {
restApi = new RallyRestApi(
new URI(host),
username,
password);
restApi.setApplicationName(applicationName);
System.out.println(restApi.getWsapiVersion());
QueryRequest releaseRequest = new QueryRequest("Release");
releaseRequest.setFetch(new Fetch("ReleaseStartDate", "ReleaseDate"));
releaseRequest.setScopedDown(false);
releaseRequest.setScopedUp(false);
releaseRequest.setProject(projectRef);
releaseRequest.setQueryFilter(new QueryFilter("Name", "=", "r1"));
QueryResponse releaseQueryResponse = restApi.query(releaseRequest);
int numberOfReleasesInProject = releaseQueryResponse.getTotalResultCount();
System.out.println(numberOfReleasesInProject);
JsonObject releaseJsonObject = releaseQueryResponse.getResults().get(0).getAsJsonObject();
System.out.println(releaseJsonObject.get("ReleaseStartDate"));
System.out.println(releaseJsonObject.get("ReleaseDate"));
String rsd = releaseJsonObject.get("ReleaseStartDate").getAsString();
String rd = releaseJsonObject.get("ReleaseDate").getAsString();
QueryRequest iterationRequest = new QueryRequest("Iteration");
iterationRequest.setFetch(new Fetch("Name","StartDate","EndDate"));
iterationRequest.setScopedDown(false);
iterationRequest.setScopedUp(false);
iterationRequest.setProject(projectRef);
iterationRequest.setQueryFilter(new QueryFilter("StartDate", ">=", rsd).and(new QueryFilter("EndDate", "<=", rd)));
QueryResponse iterationQueryResponse = restApi.query(iterationRequest);
int numberOfIteraitons = iterationQueryResponse.getTotalResultCount();
System.out.println("numberOfIteraitons " + numberOfIteraitons);
if(numberOfIteraitons >0){
for (int i=0;i<numberOfIteraitons;i++){
JsonObject iterationJsonObject = iterationQueryResponse.getResults().get(i).getAsJsonObject();
String iterationName = iterationJsonObject.get("Name").getAsString();
System.out.println("iteration: " + iterationName);
QueryRequest storyRequest = new QueryRequest("HierarchicalRequirement");
storyRequest.setProject(projectRef);
storyRequest.setFetch(new Fetch(new String[] {"Name", "FormattedID","ScheduleState"}));
storyRequest.setLimit(1000);
storyRequest.setScopedDown(false);
storyRequest.setScopedUp(false);
storyRequest.setQueryFilter(new QueryFilter("Iteration.Name", "=", iterationName));
QueryResponse storyQueryResponse = restApi.query(storyRequest);
System.out.println("Number of stories in " + iterationName + " :" + storyQueryResponse.getTotalResultCount());
for (int j=0; j<storyQueryResponse.getResults().size();j++){
JsonObject storyJsonObject = storyQueryResponse.getResults().get(j).getAsJsonObject();
System.out.println("Name: " + storyJsonObject.get("Name") + " FormattedID: " + storyJsonObject.get("FormattedID") + " ScheduleState: " + storyJsonObject.get("ScheduleState"));
}
}
}
}
finally{
if (restApi != null) {
restApi.close();
}
}
}
}
UPDATE: as far as your question in the comment, the code above is equivalent of
https://rally1.rallydev.com/slm/webservice/v2.0/hierarchicalrequirement?query=((Iteration.Name = i1) AND (Project = /project/12352608219))
There are other ways to achive the same result. Iteration name may not be unique, hence the second condition by project ref. In the code the request's project is set first, that's why the query itself uses one condition, but effectively there are two. If you know your iteration's ref, or ObjectID then the same result will be returned from (Iteration = /iteration/123456789), and there is no need to filter by project since a reference or ObjectID are unique.
WS API doc is interactive.Test your queries in WS API and copy the resulting query URLs from the address bar if you want to see how queries are formed:
-Query in the context of the intended object: click on the work item type in the Object Model, e.g. Defect or HierarchicalRequirement before typing your query in the query box.
-Enter a query in a box, e.g (Iteration.Name = i1)
-Click on Query button
-Results are displayed in the window from which you can copy query URL from address bar of your browser.
I'm working on modifying an existing application and I've decided to work with these 2 things.
My unmapped object is a simple object that consists of 2 integer properties:
public class EmployeeScore {
private int id;
private int score;
}
and I have a DAO which does the following:
public List<EmployeeScore> findEmployeeTotals(int regionId, int periodId) {
DataVerify.greaterThan(regionId, 0, "Invalid Region id: Region Id cannot be zero");
DataVerify.lessThan(regionId, 4, "Invalid Region id: Region id cannot be greater than 3");
List<EmployeeScore> results = (List<EmployeeScore>) currentSession().createSQLQuery(
"select n.EMP_ID, SUM(DISTINCT(nom.TOTAL_POINT)) from" +
" NOMINEE n join NOMINATION nom on nom.NOM_ID = n.NOM_ID" +
" join EMPLOYEE e on n.EMP_ID = e.EMP_ID" +
" join COMPANY c on c.COMPANY_CODE = e.COMPANY_CODE" +
" join REGION r on r.REGION_ID = c.REGION_ID" +
" where nom.PERIOD_ID = :periodId" +
" AND nom.STATUS_ID = 2" +
" AND e.ISACTIVE = 1" +
" AND nom.CATEGORY_CODE != 'H'" +
" AND r.REGION_ID = :regionId" +
" group by n.EMP_ID")
.setParameter("regionId", regionId)
.setParameter("periodId", periodId)
.list();
return results;
}
It's a huge query i know. I'm having problems on my tests and I assume because I'm not understanding how to apply these 2 correctly.
My test goes as follows:
#Test
#Transactional(isolation = Isolation.SERIALIZABLE)
public void testEmpScore() {
NomPeriod period = nomPeriodHibernateDAO.findById(6);
Region region = regionHibernateDAO.findById(1);
List<EmployeeScore> results = winnerHibernateDAO.findEmployeeTotals(region.getId(), period.getId());
results.toString();
Assert.assertEquals(13, results.size());
}
It should return 13 objects type EmployeeScore but instead it returns 0 so the test fails.
Can you point me in the right direction of what I'm doing wrong? I know it has to be something with my object seeing as it is not mapped but I have no way of mapping the score value or the id value since they reference different tables or aggregates.
Thanks.
The problem is that you are querying for two integers and trying to interpret them as EmployeeScores. Hibernate can do it but it will take a bit more work than that.
Assuming EmployeeScore has a constructor that takes two integers, you can try
select new my.package.EmployeeScore(n.EMP_ID, SUM(DISTINCT(nom.TOTAL_POINT))) ...
You need to give it the full package path to your object.
Alternatively, by default, I think the query will return a List<Object[]>. So you could iterate through these and form your employee scores manually.
List<Object[]> results = query.list();
List<EmployeeScore> scores = new LinkedList<EmployeeScore>();
for (Object[] arr : results)
{
int id = (int) arr[0];
int total = (int) arr[1];
scores.add(new EmployeeScore(id, total));
}