Neo4j python binding: Querying node index for a set of values - lucene

I have a Neo4j database graphDb where nodes have a property 'label'. I have a Lucene index 'my_nodes' with key 'label' which indexes the values of node property 'label'. Now I want to retrieve nodes which have property 'label' equal to a value from a list of possible values labellist. To accomplish this, I wrote a Cypher query the following way:
cypherQ = """START n=node:my_nodes('"""
+' OR '.join(['label:'+str(i) for i in labellist]) + """')
RETURN n"""
result = graphDb.query(cypherQ)
That works fine, but I wonder whether there is a way to write a parameterized query anyhow?
I tried something like:
cypherQ = """START n=node:my_nodes('label:{params}')
RETURN n"""
result = graphDb.query(cypherQ, params = labellist)
But this surely does not work, though if there is one value in labellist it works. And the neo4j tutorial does not provide much material on this issue.
Once again I am using a python binding for Neo4j.

The parameter is working for the whole query part of the index, so this would be
cypherQ = """START n=node:my_nodes({queryParam})
RETURN n"""
and you construct the query in your client code and pass it into Cypher as one parameter.

Related

ADO.NET - Accessing Each DataView in DataViewManager

Looks like a silly question, but I can't find a way to access the DataViews in my DataViewManager.
I can see it in the DataViewManager Visualizer window, so there must be a way.
What am I doing wrong?
dvm = New DataViewManager(MyDS) ''-- MyDS is a strongly typed dataset
dvm.CreateDataView(MyDS.Company)
dvm.CreateDataView(MyDS.Sites)
MsgBox(dvm.DataViewSettings.Count) ''-- shows 7, even though I added only 2.
For Each view As DataView In dvm ''-- Error!
MsgBox(view.Table.TableName)
Next
I also observed that irrespective of how many DataViews I create, data the DataViewManager Visualizer shows all DataViews in my dataset. Why?
how do I hide those rows in parent whose child data view returns 0 rows after applying RowFilter on child
I've done it like this, but it feels like a nasty hack; I've never read the source deeply enough to know if there is a better way:
Add a column to your child datatable: Name: IsShowing, Type: Int, Expression: 1, ReadOnly: True
Put the following code:
ChildBindingSource.RemoveFilter()
ParentBindingSource.RemoveFilter()
YourDataSet.ChildDataTable.IsShowingColumn.Expression = ""
YourDataSet.ChildDataTable.Expression = $"IIF([SomeColumn] Like '{SomeFilterText}',1,0)"
ChildBindingSource.Filter = "[IsShowing] > 0"
ParentBindingSource.Filter = "Sum(Child.IsShowing) > 0"
The removal and re-add triggers a re-evaluation of the expression and the filters. There is probably a way to do this without removing/re-adding but I haven't yet found it.. Expressions are normally only re-evaluated when row data changes; changing an expression doesn't seem to recalculate all the row values/trigger a refresh of the relations and BS filters
It would be great if the parent filter supported complex expressions like SUM(IIF(Child.SomeColumn = 'SomeFilter',1,0)>0 but the SUM operator expects only a column name in the parent or child. As such, the circuitous route of having a column with an Expression be the part inside the SUM is the only way i've found to leverage the built in filtering
Remember when you test that the search is case sensitive. If you want it not to be you might have to have another column of data that is the lowercase version of what you want to search and lowercase your query string

Ruby array as parameter to a plain SQL Query

I'm building a command line application that needs to connect in various postgresql databases and execute different queries in the ones as Prepared Statements. In a specific query, I need to use the IN clause in conjunction with the ActiveRecord's connection_raw method. My code is so:
ActiveRecord::Base.connection_raw.prepare('read_publications', "UPDATE publications SET readed = TRUE WHERE id IN ($1);")
After, I try execute this query:
ActiveRecord::Base.connection_raw.exec_prepared('read_publications', [1,2,3,4])
The problem is this is not working. The following error is raised when the query runs:
no implicit conversion of Array into Integer
What I'm doing wrong? Exists a way in that I can convert this array to a value that the IN clause can understand?
If you are using a raw connection, you can't pass in arrays like you can with ActiveRecords. ActiveRecord does some preprocessing for you. If you need raw SQL, then you need a parameter for each array element.
arr = [1,2,3,4]
i = 1
param = []
arr.each { param.push(i); i+=1; }
sql = "UPDATE publications SET readed = TRUE WHERE id IN ($"+param.join(',$')+");"
ActiveRecord::Base.connection_raw.prepare('read_publications', sql)
ActiveRecord::Base.connection_raw.exec_prepared('read_publications', arr)
However, the documentation says the array parameters has to be in a certain format:
https://deveiate.org/code/pg/PG/Connection.html#method-i-exec_prepared
params is an array of the optional bind parameters for the SQL query. Each element of the params array may be either:
a hash of the form:
{:value => String (value of bind parameter)
:format => Fixnum (0 for text, 1 for binary)
}
See similar question: Prepare and execute statements with ActiveRecord using PostgreSQL

Neo4J create temp variable within Cypher

So my Top-Level problem is I am trying to return whether a MERGE resulted in the creation of a new Node or not.
In order to do this I was thinking I could just create a simple temp boolean setting it to TRUE using ON CREATE
How I imagine it working:
MERGE(: Person {id:'Tom Jones'})
WITH false as temp_bool
ON CREATE set temp_bool = true
RETURN temp_bool
Obviously this does not work.
I am looking for a way to create arbitrary temp values within a Cypher query, and have the ability to return those variables in the end.
Thanks
You can do what you want, here's how (combination of my first answer, with #cybersam's addition). You just do it with a node property you create and then remove, instead of an unbound variable as you've been trying.
MERGE(tom:Person {id:'Tom Jones'})
ON CREATE set tom.temp_bool = true
ON MATCH set tom.temp_bool = false
WITH tom, tom.temp_bool AS result
REMOVE tom.temp_bool
RETURN result;
In simple merging cases like this where maximum one node could be created, a cleaner way to achieve what you are looking for could be checking the result stats. I case of using Bolt API you should check:
results.consume().counters.nodes_created = 1

Lucene indexes in Neo4j don't work as expected

I think that the title is a little bit vague, so I'm going to explain precisely my problem.
I am creating some nodes in Neo4j and then index them like this :
Index<Node> myindex = graphDb.index().forNodes(
"myindex",
MapUtil.stringMap(IndexManager.PROVIDER, "lucene", "type",
"fulltext"));
Node n = graphDb.createNode(); //create the node
node.setProperty("firstname", "firstname"); //add properties
node.setProperty("familyname", "familyname");
myindex.add(node, "familyname", "familyname"); //index it
But when I need to update Node "n" 's properties (for instance change "familyname" to "fname"), this node can't be found anymore through an index based search!
So before updating the property, this cypher query
start n= node:myindex(familyname:"familyname") return n
was returning the Node, whereas after update, I am expecting :
start n= node:myindex(familyname:"fname") return n
to return the same node with the new property, but it doesn't work ! While the first query is always working, like if the index is bound to the property "familyname"
Any thoughts about this ?
Thanks
So as tstorms suggested, the solution is to remove the index after updating the property :
n.setProperty("familyname","fname");
myindex.remove(n);
then add it with the new property :
myindex.add(n, "familyname","fname");

Does CDbcommand method queryAll() in yii return indexed entries only?

I am trying to retrieve data from a simple mySql table tbl_u_type which has just two columns, 'tid' and 'type'.
I want to use a direct SQL query instead of the Model logic. I used:
$command = Yii::app()->db->createCommand();
$userArray = $command->select('type')->from('tbl_u_type')->queryAll();
return $userArray;
But in the dropdown list it automatically shows an index number along with the required entry. Is there any way I can avoid the index number?
To make an array of data usable in a dropdown, use the CHtml::listData() method. If I understand the question right, this should get you going. Something like this:
$command = Yii::app()->db->createCommand();
$userArray = $command->select('tid, type')->from('tbl_u_type')->queryAll();
echo CHtml::dropdownlist('my_dropdown','',CHtml::listData($userArray,'tid','type'));
You can also do this with the Model if you have one set up for the tbl_u_type table:
$users = UType::model()->findall();
echo CHtml::dropdownlist('my_dropdown','',CHtml::listData($users ,'tid','type'));
I hope that gets you on the right track. I didn't test my code here, as usual, so watch out for that. ;) Good luck!