How do I query for paths in spring data neo4j 4? - spring-data-neo4j

In an earlier version of spring data neo4j (3.3.1), I was able to query for paths in my database and return them as Iterable<EntityPath<S,E>> like this:
public interface ArgumentNodeRepository extends GraphRepository<ArgumentNode> {
#Query("START t=node({0}), r=node({1}) MATCH p=t<-[:SUPPORTED_BY|INTERPRETS*0..]-r RETURN p")
Iterable<EntityPath<ArgumentNode, ArgumentNode>> getPaths(long childId, long rootId);
}
I'm trying to migrate to 4.0.0 and the EntityPath class seems to have disappeared. I don't see any mention of EntityPath in the migration guide. What's my new return type?

EntityPath isn't supported in SDN 4, but you can still query for paths.
I have an example here which contains a Cypher query that returns a path- the return type is Iterable<Map<String, Object>>
This represents a collection of paths, each path containing a list of interleaved nodes and relationships in the path (nodes and relationships represented as a Map). An example of how I processed the path is https://github.com/luanne/flavorwocky/blob/sdn/src/main/java/com/flavorwocky/service/PairingServiceImpl.java#L57

You could also Neo4jOperations for this.
Just create a custom repository implementation (see http://docs.spring.io/spring-data/data-commons/docs/current/reference/html/#repositories.custom-implementations), and call the Neo4jOperations bean from there:
neo4jOperations.queryForObjects(ArgumentNode.class, "START t=node({0}), r=node({1}) MATCH p=t<-[:SUPPORTED_BY|INTERPRETS*0..]-r RETURN p")
This will return a list of ArgumentNodes

Related

Django annotate count in JSONField with Postgres

Using Django I have a field which is of type JSONField. I am wanting to get a distinct count on a nested key/value in the json. With a normal field you can just do soemthing like the following
model.objects.values('field_name')\
.annotate(total=Count('field_name')).order_by('-total')
This does not work for a JSONField.
Example Model
class Pet(models.Model):
data = JSONField()
Example of data
{
'name':'sparky',
'animal':'dog',
'diet':{
'breakfast':'biscuits',
'dinner':'meat',
}
}
Trying
Pet.objects.values('data__diet__dinner')\
.annotate(total=Count('data__diet__dinner')).order_by('-total')
Exception of
TypeError: unhashable type: 'list'
What is the correct way to execute this?
You can use jsonb_extract_path_text via a Func object as an alternative to the field transform:
Pet.annotate(dinner=Func(
F('data'), Value('diet'), Value('dinner'),
function='jsonb_extract_path_text')) \
.values('dinner') \
.annotate(total=Count('dinner'))
The reason why the field transform data__diet__dinner fails is an error within Django when you go deeper than just one level into the json structure and use GROUP BY in the SQL. The first level (name, animal, diet) should work fine.
The reason seems to be that for nested transforms, Django changes the SQL syntax used, switching from a single value to a list to specify the path into the json structure.
This is the syntax used for non-nested json transforms (= first level):
"appname_pet"."data" -> 'diet'
And this is the syntax used for nested transforms (deeper than first level):
"appname_pet"."data" #> ARRAY['diet', 'dinner']
While constructing the query, Django chokes on that list while working out the required GROUP BY clauses. This does not seem to be an inevitable restriction; the support for transforms is quite new, and this is possibly one of the kinks that haven't been worked out yet. So if you open a Django ticket, this might just work a few versions down the line.

DJANGO API REST FRAMEWORK: schema methods

Django 1.11.3, python 3.6
I have 2 classes in my view.py:
class ProductList(generics.ListAPIView):
class SampleList(generics.ListAPIView):
Please note the same superclass. Might be relevant: Product is an actual model, Sample is not, SampleList is just a method that calls Product.objects.all() (same code as in ProductList)
All the code inside those classes besides class names is IDENTICAL (including serializer) - I just copied the class and renamed the copy).
The client before it hits urls for those two gets the schema
schema = self.client.get(self.myAppApiUrl)
#works, returns the results
result1 = self.client.action(schema, ["products", "list"])
params = {"id" : some_id, }
#fails with this: coreapi.exceptions.LinkLookupError: Index ['samples']['list'] did not reference a link. Key 'list' was not found.
result2 = self.client.action(schema, ["samples", "list"], params)
When I print "schema", I see
products: {
list([page])
}
samples: {
read(id)
}
My questions are: what makes it to add "list" to schema in the first case and "read" in the second case? And how can I add "list" to the second case? Maybe some schema update needs to be done somehow? The API web server was restarted.
What does that message "Key 'list' was not found" mean? Does this failure have something to do with the params passed? Removing params from the client call does not change anything.
I am also somewhat curious about what is that "page" thing in list and what adds that and but that's not important.

Serializing enum fields spring data solr

I have this field in my domain object
#Field
#Enumerated(EnumType.STRING)
private SectionType sectionType;
but when I check the value stored in Solr it is something like:
com.x.y.objects.SectionType:H_HPI
What I want is just H_HPI or it is as if I'm calling specialty.name() method
Also I want a serializer that does that for all the enum fields in my domain objects.
I know that for neo4j, for instance, has such a serializer and can be supplied to the field as an annotation. Also mongodb does the conversion automatically.
I had same problem and found this from Spring Data Solr codes
else if (fieldValue instanceof Enum) {
field.setValue(this.getConversionService().convert(fieldValue, String.class), 1f);
}
it sets the String value
https://github.com/spring-projects/spring-data-solr/commit/4bf0af3344ec9e92ac241eaa25883e73b08f3b0b

How sitecore 7 maps template with class

I have downloaded Sitecore 7 Autohaus demo for learning purpose.
I notice that in Autohaus code, there is a model - Car.
I would like to know how does sitecore know how to map between Car model (code) and CarModel template (sitecore template).
There are a few more steps between the car template and the car object model.
One of the main features of Sitecore 7 is the embedded search capability. When items, created from the car template, are saved, that information is stored in a search index (Lucene or Solr)
The Car model is not mapped directly from the template or the database item but from the search document created.
When you use the LINQ layer e.g.
var index = ContentSearchManager.GetIndex("sitecore_master_index");
using (var context = index.CreateSearchContext())
{
var query= context.GetQueryable<Car>()
.Where(item => item.Seats == 2);
}
Sitecore will execute a search and then take the 'Car' object and populate/hydrate it with the information from the search results by use of Sitecore's DocumentMapper.
This will populate public properties and also indexers of the Car object. The DocumentMapper takes care of casting to and from object types for you (such as DateTime / int etc).
The DocumentMapper will try and map properties with matching field names but you can place attributes on the object properties to help Sitecore map specifically to your objects.
This example tells Sitecore to map the field 'modelkey' to the property ModelId.
[IndexField("modelkey")]
public string ModelId { get; set; }
You can see the LINQ queries used in Autohaus on most of the pages and should be a great resource for learning how Sitecore 7 works.
More info about various parts of Sitecore 7 can be found here: http://www.sitecore.net/Community/Technical-Blogs/Sitecore-7-Development-Team.aspx

Partial text search with postgreql & django

Tried to implement partial text search with postgresql and django,used the following query
Entry.objects.filter(headline__contains="search text")
This returns records having exact match,ie suppose checking for a match against the record "welcome to the new world" with query __contains="welcome world" , returns zero records
How can i implement this partial text search with postgresql-8.4 and django?
If you want this exact partial search you can use the startswitch field lookup method: Entry.objects.filter(headline__startswith="search text"). See more info at https://docs.djangoproject.com/en/dev/ref/models/querysets/#startswith.
This method creates a LIKE query ("SELECT ... WHERE headline LIKE 'search text%'") so if you're looking for a fulltext alternative you can check out PostgreSQL's built in Tsearch2 extension or other options such as Xapian, Solr, Sphinx, etc.
Each of the former engines mentioned have Django apps that makes them easier to integrate: Djapian for Xapian integration or Haystack for multiple integrations in one app.