No result with Cypher after batchinserting with indexing - neo4j

I'm very new to neo4j. I've read this question (Cypher Query not finding Node) but it does not work. I'm getting the error, the the auto_node_index was not found. Perhaps it is because I'm using the BatchInserter?
For my experiment, I'm using neo4j 1.8.2 and the programming language Java with the embedded database.
I want to put some data to the database using the BatchInserter and the BatchInserterIndex like explained on http://docs.neo4j.org/chunked/milestone/batchinsert.html.
BatchInserter myInserter = BatchInserters.inserter(DB_PATH);
BatchInserterIndexProvider indexProvider =
new LuceneBatchInserterIndexProvider( myInserter );
BatchInserterIndex persons =
indexProvider.nodeIndex( "persons", MapUtil.stringMap( "type", "exact" ) );
persons.setCacheCapacity( "name", 10000 );
First I read the data from a TGF-file, create the nodes and put it to the inserter like this:
properties = MapUtil.map("name", actualNodeName, "birthday", birthdayValue);
long node = myInserter.createNode(properties);
nodes.add(node);
persons.flush();
The insert works fine, but when I want to search a node with Cypher, the result is empty
ExecutionEngine engine = new ExecutionEngine( db );
String query =
"start n=node:persons(name='nameToSearch') "
+ " match n-[:KNOWS]->m "
+ " return n.id, m ";
ExecutionResult result = engine.execute( query );
System.out.println(result);
On the other side, when I'm using the Traverser-class and start the search on the rootnode, I receive the nodes wich are connetced by the node with the name "nameToSearch".
Can anybody explain me, why I can't get the nodes with Cypher!
here is the complete method for the batch insert:
public long batchImport() throws IOException{
String actualLine;
ArrayList<Long> nodes = new ArrayList<Long>();
Map<String,Object> properties = new HashMap<String,Object>();
//delete all nodes and edges in the database
FileUtils.deleteRecursively(new File(DB_PATH ));
BatchInserter myInserter = BatchInserters.inserter(DB_PATH);
BatchInserterIndexProvider indexProvider =
new LuceneBatchInserterIndexProvider( myInserter );
BatchInserterIndex persons =
indexProvider.nodeIndex( "persons", MapUtil.stringMap( "type", "exact" ) );
persons.setCacheCapacity( "name", 10000 );
long execTime = 0;
try{
//Get the file which contains the graph informations
FileReader inputFile = new FileReader(UtilFunctions.searchFile(new File(PATH_OUTPUT_MERGED_FILES), "nodesAndEdges").get(0));
LineNumberReader inputLine = new LineNumberReader(inputFile);
// Read nodes up to symbol #
execTime = System.nanoTime();
while ((actualLine=inputLine.readLine()).charAt(0) != '#'){
StringTokenizer myTokenizer = new StringTokenizer(actualLine);
// Read node number
String actualNodeNumber = myTokenizer.nextToken();
// Read node name
String actualNodeName = myTokenizer.nextToken() + " " + myTokenizer.nextToken();
//Read property
myTokenizer.nextToken();
String actualNodePropertyKey = BIRTHDAY_KEY;
String actualNodePropertyValue = myTokenizer.nextToken();
actualNodePropertyValue = actualNodePropertyValue.substring(1, actualNodePropertyValue.length()-1);
// Insert node information
properties = MapUtil.map("name", actualNodeName, "birthday", actualNodePropertyValue, "id", actualNodeNumber);
long node = myInserter.createNode(properties);
nodes.add(node);
persons.flush();
}
// Read edges up to end of file
int countEdges = 0;
while ((actualLine=inputLine.readLine()) != null){
StringTokenizer myTokenizer = new StringTokenizer(actualLine);
// Read start node number
String actualStartNodeNumber = myTokenizer.nextToken();
// Read destination node number
String actualDestinationNodeNumber = myTokenizer.nextToken();
// Read relationship type
String actualRelType = myTokenizer.nextToken();
// Insert node information into ArrayList
int positionStartNode = Integer.parseInt(actualStartNodeNumber);
int positionDestinationNode = Integer.parseInt(actualDestinationNodeNumber);
properties.clear();
if (countEdges == 0) {
myInserter.createRelationship(0, nodes.get(positionStartNode-1), RelType.ROOT, properties);
myInserter.createRelationship(nodes.get(positionStartNode-1), nodes.get(positionDestinationNode-1), RelType.KNOWS, properties);
}
else
{
myInserter.(nodes.get(positionStartNode-1), nodes.get(positionDestinationNode-1), RelType.KNOWS, properties);
}
countEdges++;
}
indexProvider.shutdown();
myInserter.shutdown();
execTime = System.nanoTime() - execTime;
// Close input file
inputLine.close();
inputFile.close();
}
catch (Throwable e){
System.out.println(e.getMessage());
e.printStackTrace();
}
return execTime;
}

Your lacks a call to profiles.add(node, <indexProperties>). Therefore you're never adding anything to the index.

It is crucial that the code using Batchinserter API calls shutdown() on both the BatchInserterIndexProvider and BatchInserter. Maybe you've missed this in your code.
If this does not solve the problem, please post your code.

Related

Log Parser 2.2 Registry Wildcard Search

I'm trying to figure out if there is a way to do a wildcard registry search using Log Parser 2.2. A sample of what I'm trying to do:
try
{
LogQuery qry = new LogQuery();
RegistryInputFormat registryFormat = new RegistryInputFormat();
string query = #"SELECT Path FROM \HKCU\Software WHERE Value='%keyword%'";
rs = qry.Execute(query, registryFormat);
for (; !rs.atEnd(); rs.moveNext())
listBox1.Items.Add(rs.getRecord().toNativeString(","));
}
finally
{
rs.close();
}
WHERE Value='%keyword%' does not seem to work and is specific to what is entered in within the '' and specifically searches %keyword% versus the percent signs being wildcards.
Okay nevermind, got it figured out:
RegRecordSet rs = null;
try
{
LogQuery qry = new LogQuery();
RegistryInputFormat registryFormat = new RegistryInputFormat();
string query = #"SELECT Path FROM \HKCU\Software WHERE Value LIKE '%keyword%'";
rs = qry.Execute(query, registryFormat);
for (; !rs.atEnd(); rs.moveNext())
listBox1.Items.Add(rs.getRecord().toNativeString(","));
}
finally
{
rs.close();
}

Can not add a list in document object using iTextSharp

public ActionResult PartTimeFacultyCourseLoadReport()
{
var teacherStatistics = (from t in db.Teachers
join c in db.Courses
on t.Id equals c.TeacherId into cGroup
where t.Status == "Part Time"
orderby t.Designation descending
select new
{
TeacherInfo = t,
CourseInfo = from cg in cGroup
orderby cg.Code ascending
select cg
}).ToList();
List<TeacherStatistics> teacherStatisticses = new List<TeacherStatistics>();
int count = 0;
foreach (var teacherStatistic in teacherStatistics)
{
TeacherStatistics aTeacherStatistics = new TeacherStatistics();
aTeacherStatistics.Name = teacherStatistic.TeacherInfo.Name;
aTeacherStatistics.Designation = teacherStatistic.TeacherInfo.Designation;
aTeacherStatistics.NumberOfCourse = teacherStatistic.TeacherInfo.NumberOfCourse;
count = 0;
foreach (var courseInfo in teacherStatistic.CourseInfo)
{
if (count != 0)
{
aTeacherStatistics.Courses += ", ";
}
aTeacherStatistics.Courses += courseInfo.Code;
aTeacherStatistics.Courses += "(";
aTeacherStatistics.Courses += courseInfo.Section;
aTeacherStatistics.Courses += ")";
count++;
}
teacherStatisticses.Add(aTeacherStatistics);
}
var document = new Document(PageSize.A4, 50, 50, 25, 25);
var output = new MemoryStream();
var writer = PdfWriter.GetInstance(document, output);
document.Open();
var data = teacherStatisticses.ToList();
document.Add(data);
Response.ContentType = "application/pdf";
Response.AddHeader("content-disposition", "attachment; filename=PartTimeFaculty.pdf");
Response.BinaryWrite(output.ToArray());
document.Close();
return View(teacherStatisticses);
}
I want to pass a list named 'teacherStatisticses' through document object for making a PDF. My code doesn't work. It showed me following Error -
Argument 1: cannot convert from 'System.Collections.Generic.List' to 'iTextSharp.text.IElement'
I assume that you are using some version of itextpdf for the PDF generation.
The error is in the line:
document.Add(data);
There is no way to add plain .NET objects into the PDF document. I can not predict the structure of PDF which you`d like to achieve, but the code mentioned above could be written as:
foreach(var teacher in teacherStatistics)
{
var paragraph = new Paragraph(teacher.ToString()); // instead of teacher.ToString() should be some code which translates teacherStatistics projection to the string representation
document.Add(paragraph);
}
//not tested
A lot of useful samples could be found at
http://developers.itextpdf.com/examples
Basic tutorial for the itextpdf:
http://developers.itextpdf.com/content/itext-7-jump-start-tutorial/chapter-1-introducing-basic-building-blocks

SQL CLR User Defined Function (C#) adds null character (\0) in between every existing character in String being returned

This one has kept me stumped for a couple of days now.
It's my first dabble with CLR & UDF ...
I have created a user defined function that takes a multiline String as input, scans it and replaces a certain line in the string with an alternative if found. If it is not found, it simply appends the desired line at the end. (See code)
The problem, it seems, comes when the final String (or Stringbuilder) is converted to an SqlString or SqlChars. The converted, returned String always contains the Nul character as every second character (viewing via console output, they are displayed as spaces).
I'm probably missing something fundamental on UDF and/or CLR.
Please Help!!
Code (I leave in the commented Stringbuilder which was my initial attempt... changed to normal String in a desperate attempt to find the issue):
[Microsoft.SqlServer.Server.SqlFunction]
[return: SqlFacet(MaxSize = -1, IsFixedLength = false)]
//public static SqlString udf_OmaChangeJob(String omaIn, SqlInt32 jobNumber) {
public static SqlChars udf_OmaChangeJob(String omaIn, SqlInt32 jobNumber) {
if (omaIn == null || omaIn.ToString().Length <= 0) return new SqlChars("");
String[] lines = Regex.Split(omaIn.ToString(), "\r\n");
Regex JobTag = new Regex(#"^JOB=.+$");
//StringBuilder buffer = new StringBuilder();
String buffer = String.Empty;
bool matched = false;
foreach (var line in lines) {
if (!JobTag.IsMatch(line))
//buffer.AppendLine(line);
buffer += line + "\r\n";
else {
//buffer.AppendLine("JOB=" + jobNumber);
buffer += ("JOB=" + jobNumber + "\r\n");
matched = true;
}
}
if (!matched) //buffer.AppendLine("JOB=" + jobNumber);
buffer += ("JOB=" + jobNumber) + "\r\n";
//return new SqlString(buffer.ToString().Replace("\0",String.Empty)) + "blablabla";
// buffer = buffer.Replace("\0", "|");
return new SqlChars(buffer + "\r\nTheEnd");
}
I know in my experiences, the omaIn parameter should be of type SqlString and when you go to collect its value/process it, set a local variable:
string omaString = omaIn != SqlString.Null ? omaIn.Value : string.empty;
Then when you return on any code path, to rewrap the string in C#, you'd need to set
return omaString == string.empty ? new SqlString.Null : new SqlString(omaString);
I have had some fun wrestling matches learning the intricate hand-off between local and outbound types, especially with CLR TVFs.
Hope that can help!

how can I connect to database

I use this but I can't connect DataBase
conn1.Open();
using (OracleCommand crtCommand = new OracleCommand);
for connect to Oracle from application
string command = "Enter your command";
OracleConnection orclecon;
orclecon = new OracleConnection(connection);
orclecon.Open();
use this for select commands:
DataSet ds = new DataSet();
using (OracleDataAdapter Oda = new OracleDataAdapter(command, orclecon))
{
Oda.Fill(ds);
}
and use this for insert/update/delete commands:
//used for Oracle command (insert,update,delete) if number of rows that affected >0 return true else return false
using (OracleCommand orclcommand = new OracleCommand(command, orclecon))
{
int n = orclcommand.ExecuteNonQuery();
if (n > 0)
return true;
else
return false;
}
orclecon.Close();
To make it dynamic use this;
string sentence = "";
string formatprototype = "";//This will hold the string to be formatted.
string output="";
public void SearchString()
{
string pattern = #".*[ ]+?[\""]{1}(?<String>[a-zA-Z0-9_]*)[\""]{1}[ ]+?MINVALUE[ ]*(?<MinValue>[-?\d]*)[ ]*MAXVALUE[ ]*(?<MaxValue>[\d]*)[ ]+?[INCREMENT]*[ ]+?[BY]*[ ]+?(?<IncrementBy>[\d]*)[ ]+?[START]*[ ]+?[WITH]*[ ]+?(?<StartWith>[\d]*)[ ]+?[CACHE]*[ ]+?(?<Cache>[\d]*)\s+?";
Regex regex = new Regex(pattern);
Match match = regex.Match(sentence);
Group #string = match.Groups[1];
Group minvalue = match.Groups[2];
Group maxvalue = match.Groups[3];
Group incrementby = match.Groups[4];
Group startswith = match.Groups[5];
Group cache = match.Groups[6];
formatprototype = #"CREATE SEQUENCE ""{0}"" MINVALUE {1} MAXVALUE {2} INCREMENT BY {3} START WITH {4} CACHE {5} NOORDER NOCYCLE";
if (minvalue.Value.StartsWith("-"))
{
output = string.Format(formatprototype, #string, minvalue, maxvalue, incrementby, maxvalue, cache);
}
else if (!minvalue.Value.StartsWith("-"))
{
output = string.Format(formatprototype, #string, minvalue, maxvalue, incrementby, minvalue, cache);
}
MessageBox.Show(output);
}
Assume that SearchString() is the function in which you are doing this stuff.And make sure to assign each string that is extracted from database,to sentence.Try it and reply if it worked or not.

JQL performance - natural sort for custom text field

I am struggling with a JQL query.
We have a custom field called 'Build Reported' which is a text field. It has values like '4.7.323H', '5.1.123L', '3.1.456E', etc.
I need to write a simple query that will give me all issues reported after the user-specified version.
JQL function prototype: searchIssues('Build Integrated', '>', '4.7.323B')
To do this, I am firing a JQL Query that gives me the Build Reported for all the issues, I then iterate through each issue and perform a char-by-char comparison to determine if the Build Reported version of the current issue is greater than the one specified by the user. This seems to take too long to execute since I have to retrieve all the issues from jira database.
Is there a faster way to achieve this? Here is what I have so far:
// Get all the arguments
java.util.List args = operand.getArgs();
CustomField cf = customFieldManager.getCustomFieldObjectByName((String)args.get(0));
Long cfID = cf.getIdAsLong();
String operator = (String)args.get(1);
String userVersion = (String)args.get(2);
String jiraVersion = "";
java.util.List issues;
Iterator issuesIterator;
Issue issue;
issues = getAllIssues(user, interestedInVersion, cfID);
issuesIterator = issues.iterator();
// Iterate over all the issues
while(issuesIterator.hasNext())
{
issue = (Issue)issuesIterator.next();
// Get the Build reported value
jiraVersion = (String)issue.getCustomFieldValue(cf);
if(jiraVersion != null &&
!jiraVersion.equals(""))
{
// Compare user-specified version to the one retrieved from database
if(compareVersions(jiraVersion, userVersion, operator))
{
// Add the issue to the result set
literals.add(new QueryLiteral(operand, issue.getId()));
}
}
}
// cfID is the ID for the custom field Build Reported
private java.util.List getAllIssues(User user, Long cfID) throws SearchException, ParseException
{
JqlQueryBuilder builder = JqlQueryBuilder.newBuilder();
builder.where().project("SDEV").and().customField(cfID).isNotEmpty();
Query query = builder.buildQuery();
SearchResults results = searchService.search(user, query, PagerFilter.getUnlimitedFilter());
return results.getIssues();
}
Please note that I do not have any other filters that I could use for the JQL Query Builder to help me reduce the size of the result set.
I found an alternative to the issue I described in my question. Instead of using JQL, I ended up firing a direct SELECT and this turned out to be way quicker. The function below is a part of the JQL Plugin. Here is the code:
This is what I ended up doing:
public java.util.List getValues(#NotNull QueryCreationContext queryCreationContext, #NotNull FunctionOperand operand, #NotNull TerminalClause terminalClause)
{
try
{
// User
User user = queryCreationContext.getUser();
// Args
java.util.List args = operand.getArgs();
CustomField cf = customFieldManager.getCustomFieldObjectByName((String)args.get(0));
Long cfID = cf.getIdAsLong();
String operator = (String)args.get(1);
String userVersion = (String)args.get(2);
// Locals
java.util.List literals = new java.util.LinkedList();
MutableIssue issue = null;
String issueId = "";
String jiraVersion = "";
// DB
Connection conn = null;
String url = "jdbc:jtds:sqlserver://*****:*****/jiradb";
String driver = "net.sourceforge.jtds.jdbc.Driver";
String userName = "*******";
String password = "*******";
String sqlQuery = null;
Statement statement = null;
ResultSet resultSet = null;
Class.forName(driver).newInstance();
conn = DriverManager.getConnection(url, userName, password);
// Get all the issues that has the custom field set
sqlQuery = " SELECT t2.id AS IssueId, t1.stringvalue AS JiraVersion " + "\n" +
" FROM jiradb.jiraschema.customfieldvalue t1 " + "\n" +
" INNER JOIN jiradb.jiraschema.jiraissue t2 " + "\n" +
" ON t1.issue = t2.id " + "\n" +
" WHERE t1.customfield = " + Long.toString(cfID) + " " + "\n" +
" AND t1.stringvalue IS NOT NULL " + "\n" +
" AND t1.stringvalue != '' " + "\n" +
" AND t2.pkey LIKE 'SDEV-%' ";
// Iterate over the result set
statement = conn.createStatement();
resultSet = statement.executeQuery(sqlQuery);
while (resultSet.next())
{
issueId = resultSet.getString("IssueId");
jiraVersion = resultSet.getString("JiraVersion");
// Compare the version from jira with the user provided version
// This is my own function that does char-by-char comparison
if(compareVersions(jiraVersion, userVersion, operator))
{
// Get the issue object to add to the result
issue = ComponentManager.getInstance().getIssueManager().getIssueObject(Long.parseLong(issueId));
// Add the issue to the result
literals.add(new QueryLiteral(operand, issue.getId()));
}
}
// Return all the matching issues here
return literals;
}
catch(Exception e)
{
// Exception handling
}
return null;
}
And this is how the plugin is used:
issue in searchIssues('Build Reported', '>', '5.1.104');

Resources