Neo4j Spring Data Query Builder - spring-data-neo4j

Is there a way of dynamically building a cypher query using spring data neo4j?
I have a cypher query that filters my entities similar to this one:
#Query("MATCH (n:Product) WHERE n.name IN {0} return n")
findProductsWithNames(List<String> names);
#Query("MATCH (n:Product) return n")
findProductsWithNames();
When the names list is empty or null i just want to return all products. Therefore my service impl. checks the names array and calls the correct repository method. The given example is looks clean but it really gets ugly once the cypher statements are more complex and the code starts to repeat itself.

You can create your own dynamic Cypher queries and use Neo4jOperations to execute them. Here is it an example (with a query different from your OP) that I think can ilustrate how to do that:
#Autowired
Neo4jOperations template;
public User findBySocialUser(String providerId, String providerUserId) {
String query = "MATCH (n:SocialUser{providerId:{providerId}, providerUserId:{providerUserId}})<-[:HAS]-(user) RETURN user";
final Map<String, Object> paramsMap = ImmutableMap.<String, Object>builder().
put("providerId", providerId).
put("providerUserId", providerUserId).
build();
Map<String, Object> result = template.query(query, paramsMap).singleOrNull();
return (result == null) ? null : (User) template.getDefaultConverter().convert(result.get("user"), User.class);
}
Hope it helps

Handling paging is also possible this way:
#Test
#SuppressWarnings("unchecked")
public void testQueryBuilding() {
String query = "MATCH (n:Product) return n";
Result<Map<String, Object>> result = neo4jTemplate.query(query, Collections.emptyMap());
for (Map<String, Object> r : result.slice(1, 3)) {
Product product = (Product) neo4jTemplate.getDefaultConverter().convert(r.get("n"), Product.class);
System.out.println(product.getUuid());
}
}

Related

How to store and use opening hour information in flutter firebase?

I am building an app in flutter which requires the storage of opening hours in firebase. I have decided to store the data in this format:
0: [9,17], //Monday
1: Null, //Tuesday
Etc Etc. The openingHours field is a list of map values. The key corresponds to the day, then the hours are the value, being a list of integers if open, or a null value if closed. I am struggling however to take the list from the json file from firebase and store it in a list of maps value in flutter, in a class called "business", and similarly upload the data to flutter.
The business object looks like this:
class Business{
String businessId;
String name;
String photoUrl;
Map<int, List<int>> openingHours;
CommentModel({
this.name,
this.businessId,
this.photoUrl,
this.openingHours
});
CommentModel.fromJson(Map<String, dynamic> json) {
name = json['name'];
businessId = json['businessId'];
photoUrl = json['photoUrl'];
openingHours = json['openingHours'];
}
Map<String, dynamic> toJson() {
final Map<String, dynamic> data = new Map<String, dynamic>();
data['name'] = this.name;
data['businessId'] = this.businessId;
data['photoUrl'] = this.photoUrl;
data['openingHours'] = this.openingHours;
return data;
}
}
I am pretty aware I'm quite far off the mark with this one and would appreciate any help before I fully try and implement this into my currently working elsewhere design and cause some irreversible damage XD.
0: {"open": "7:00","close: "20:00"}
1: null,
2: {"open": "7:00","close: "20:00"}

Create XML dataset with the same table name as initial data set in DBUnit?

I'm trying to create an initial DB state in DB Unit like this...
public function getDataSet() {
$primary = new \PHPUnit\DbUnit\DataSet\CompositeDataSet();
$fixturePaths = [
"test/Seeds/Upc/DB/UpcSelect.xml",
"test/Seeds/Generic/DB/ProductUpcSelect.xml"
];
foreach($fixturePaths as $fixturePath) {
$dataSet = $this->createXmlDataSet($fixturePath);
$primary->addDataSet($dataSet);
}
return $primary;
}
Then after my query I'm attempting to call this user-defined function...
protected function compareDatabase(String $seedPath, String $table) {
$expected = $this->createFlatXmlDataSet($seedPath)->getTable($table);
$result = $this->getConnection()->createQueryTable($table, "SELECT * FROM $table");
$this->assertTablesEqual($expected, $result);
}
The idea here is that I have an initial DB state, run my query, then compare the actual table state with the XML data set representing what I expect the table to look like. This process is described in PHPUnit's documentation for DBUnit but I keep having an exception thrown...
PHPUnit\DbUnit\InvalidArgumentException: There is already a table named upc with different table definition
Test example...
public function testDeleteByUpc() {
$mapper = new UpcMapper($this->getPdo());
$mapper->deleteByUpc("someUpcCode1");
$this->compareDatabase("test/Seeds/Upc/DB/UpcAfterDelete.xml", 'upc');
}
I seem to be following the docs...how is this supposed to be done?
This was actually unrelated to creating a second XML Dataset. This exception was thrown because the two fixtures I loaded in my getDataSet() method both had table definitions for upc.

Testing criteria creation in a Grails service

I have a Grails service that creates a criteria query with optional parameters like this:
List<Car> search(String make = "%", String model = "%", Integer year = null) {
def c = Car.createCriteria()
return c.list() {
if(make) {
like("make", make)
}
if(model) {
like("model", model)
}
if(year) {
eq("year", year)
}
}
}
(Also, is this the idiomatic way to do this in grails? I'm quite new to the framework and I'm trying to find the right way to do things)
I'd like to test that the proper criteria filters are set according to the values of the parameters of the search method but I'm having no success.
I tried some variations of this:
#TestFor(CarService)
#Mock(Car)
class CarServiceSpec extends Specification {
def car = Mock(Car)
void "empty filters"() {
when: service.search()
then:
with(car.createCriteria()) {
0 * like(*_)
0 * eq(*_)
}
}
}
But I can't seem to find a way to do assertions about the interactions between the CarService and the criteria object.
What am I missing?
The Grails Where query instead of the Criteria query seems to be better choice for an idiomatic way to do this in Grails:
Gorm Where Query

Neo4j: spring-data-neo4j,how to cast result to my type class?

I have insert some node into Neo4j DB.And I want to select some node from database and cast it to specific class.
Here are some code about the problem:
class Service {
Neo4jTemplate neo4jTemplate
#Transactional
def find() {
def id1 = 11
//Knowledge k = neo4jTemplate.findOne(1, Knowledge)
Result result = neo4jTemplate.query("start n=node(11) return ID(n),n.name,n.age;", null)
//how to cast the result to User class
println "the tpye of result called User is "+ result.to(User.class).is(cn.edu.bnuz.itc.bok.sub2.User.class)
}
}
The detail about node like :
+-------------------------------------------------------------------------+
| Node[11]{career:"programmer",name:"kelvin",age:35,introduce:"lazy doy"} |
+-------------------------------------------------------------------------+
#NodeEntity
class User {
#GraphId
Long id;
String name;
int age;
}
I just want get the node's id, name, age from db and put it into a User class.
But it failed many time with many method.
Here I have encounter a problem which is :How can I cast the result to my target class? I have try many method to cast but fail finally.Thank you for you attention.
Return the user node from the query and call the to method of the returned Result with the desired class as argument:
Result result = neo4jTemplate.query("start n=node(11) return n", null);
for(User u : result.to(User.class)) {
doSomethingWith(u);
}
You may want to consider using repositories that support cypher queries like:
public interface UserRepository extends GraphRepository<User> {
#Query("start n=node(11) return n")
Iterable<User> getUser11();
}

Why does my XML ASP.NET web service return results which repeats itself?

I have written an ASP.NET web service.
It looks like this:
WebServices.logic pLogic = new WebServices.logic();
WebServices.manager[] pManager = new PowerManager[1];
pManager[0] = new PowerManager();
pManager[0].CustomerId = "sjsjshd";
pManager[0].state = pLogic.getState("sasj");
return pManager[0];
The pManager class looks like this:
public string _CustomerId;
public int PowerStatus;
public List<ArrayList> _Power;
public string CustomerId
{
get
{
return _CustomerId;
}
set
{
_CustomerId = value;
}
}
public List<ArrayList> Power
{
get
{
return _Power;
}
set
{
_Power = value;
}
}
When I run it, I get a repetition of the results, like so:
<p>
<_CustomerId>sjsjshd</_CustomerId>
<pStatus>0</PowerStatus>
−
<_p>
−
<ArrayOfAnyType>
<anyType xsi:type="xsd:int">1</anyType>
</ArrayOfAnyType>
<ArrayOfAnyType/>
</_p>
<CustomerId>sjsjshd</CustomerId>
−
<p>
−
<ArrayOfAnyType>
<anyType xsi:type="xsd:int">1</anyType>
</ArrayOfAnyType>
<ArrayOfAnyType/>
</p>
</pManager>
However, there is no duplicate values stored (Eg. I store client name in a collection, but only once - count of 1). There are no duplicates stored when I call getState(). This method returns a collection and it contains one value, but the results in XML has a repetition of this.
How comes the results appear to repeat themselves? When running the system, I only get one error.
Thanks
OK, looks like your XML serialization is giving you all the public members of your PowerManager class. Based on the naming convention of starting with an underscore, those members should be private, like this:
private string _CustomerId;
private List<ArrayList> _Power;
You also state "When running the system, I only get one error." What error are you getting?