The ontology lies in XML here.
I also tried to ask which are the classes of my world and then tried to check if my resource (the municipality) really belongs to that class, but still Country slips away (although it's fetched when I ask for all the classes, it fails to connect via the property belongs_to to my resource).
I have also enabled Forward chaining for reasoning in Sesame! BTW, I am a beginner, so any tip would be gold to me. What am I missing?
Edit:
New query:
"SELECT ?res ?belongs " +
"WHERE {" +
"?res a geo:Mun ;"+
"geo:hasName \"mun name\" ;"+
"geo:belongs_to+ ?belongs ."+
"}";
Output:
[belongs=http://geo.linkedopendata.gr/gag/id/1304;res=http://geo.linkedopendata.gr/gag/id/9325]
[belongs=http://geo.linkedopendata.gr/gag/id/13;res=http://geo.linkedopendata.gr/gag/id/9325]
[belongs=http://geo.linkedopendata.gr/gag/id/997;res=http://geo.linkedopendata.gr/gag/id/9325]
If I understand your data model correctly, you have instances of class geo:Municipality, which belong to an instance of geo:RegionUnit, which in turn belongs to an instance of geo:Region, etc, until ultimately they belong to an instance of geo:Country. And unless I misunderstand, your query tries to get back all these instances for one particular munipicality.
This is quite simply done, and does not even require any RDFS inferencing support.
Let's build up the query one step at a time. First, let's grab the actual municipality itself:
SELECT ?res
WHERE {
?res a geo:Municipality ;
geo:έχει_επίσημο_όνομα "ΔΗΜΟΣ ΧΑΝΙΩΝ" .
}
I'm assuming here (since I don't speak Greek) that geo:έχει_επίσημο_όνομα is the RDF property that links the Municipality resource with its name label.
The second step is that we want to grab all other resources it belongs to.
SELECT ?res ?belongs
WHERE {
?res a geo:Municipality ;
geo:έχει_επίσημο_όνομα "ΔΗΜΟΣ ΧΑΝΙΩΝ" ;
geo:belongsTo ?belongs .
}
Of course, the above only gets us back the things that it directly belongs to. If we believe your ontology, this will give us back the region unit(s) it belongs to, but nothing else. But we want all of them, N steps removed, so we want to transitively follow the geo:belongsTo relation. This can be done using a transitive property path:
SELECT ?res ?belongs
WHERE {
?res a geo:Municipality ;
geo:έχει_επίσημο_όνομα "ΔΗΜΟΣ ΧΑΝΙΩΝ" ;
geo:belongsTo+ ?belongs .
}
Notice the +. This means "one or more times", so the variable ?belongs will be bound to any values that can be reached by following the geo:belongsTo property one or more times (the * that you used in your question, btw, expresses 'zero or more times').
Update
Now, if in addition to getting the individual resources, you also want to get back the classes themselves that they belong to (that is, geo:RegionUnit, geo:Country, etc), you can amend the query like so:
SELECT ?res ?belongs ?adminUnit
WHERE {
?res a geo:Municipality ;
geo:έχει_επίσημο_όνομα "ΔΗΜΟΣ ΧΑΝΙΩΝ" ;
geo:belongsTo+ ?belongs .
?belongs a ?adminUnit .
}
This will give you back all administrative units that the given municipality belongs to, and the class of each particular administrative unit. Here, by the way, RDFS inferencing will make a slight difference: because all your admin-unit classes are defined as a rdfs:subClassOf the class geo:AdministrativeUnit, you will get back two results for each unit: once the specific class, and once the superclass geo:AdministrativeUnit.
Update 2 if the problem is that you get all the administrative units back except the country, then the most likely cause of this is that the geo:belongsTo relation between the specific Decentralised Admin (Let's call it geo:DecAdm for short) and the Country is missing. If you wish to verify this, you can do the following query:
ASK WHERE {
<http://geo.linkedopendata.gr/gag/id/997> geo:belongsTo [ a geo:Country ] .
}
Replace <http://geo.linkedopendata.gr/gag/id/997> with the actual id of the geo:DecAdmin you're interested in. The query will return true if the relation exists, false otherwise.
Or if you want to check more generally, you can do the following:
SELECT ?decAdmin ?country
WHERE {
?decAdmin a geo:DecAdm .
OPTIONAL { ?decAdmin geo:belongsTo ?country .
?country a geo:Country .
}
} ORDER BY ?decAdmin
This query will give you an overview of all decentralized administration instances, and the country to which they belong. If there is no country known for a particular ?decAdmin, the second column in your query result will be empty for that row.
Related
I went through the documentation of Java api to query Grakn database.
Grakn.Transaction readTransaction = session.transaction(GraknTxType.READ);
GetQuery query = Graql.match(var("p").isa("person")).limit(10).get();
Stream<ConceptMap> answers = query.withTx(readTransaction).stream();
answers.forEach(answer -> System.out.println(answer.get("p").id()));
It's printing id, but I want to see the data, the name associated with the person. I want to see the content inside the result. It's simply showing id.
The answers provided as the result of a Graql query, is a collection of the variables (and their values) as you have specified them in the query itself.
In this case, to get the name of instances of person, you'd include it in the query like so:
GetQuery query = Graql.match(var("p").isa("person").has("name", var("n"))).limit(10).get();
The Graql equivalent being match $p isa person, has name $n; get;.
Now you can use the methods available in the Concept API to retrieve information available on each variable.
In this case, variable n holds an attribute and you'd want to retrieve its value(), like so:
answers.forEach(answer -> System.out.println(answer.get("n").asAttribute().value()))
My scenario is like this.
Solr Indexing happens for a product and then product approval status is made unapproved from backoffice. After then, when you search the related words that is placed in description of the product or directly product code from website, you get a server error since the product that is made unapproved is still placed in solr.
If you perform any type of indexing from backoffice manually, it works again. But it is not a good solution since there might be lots of products whose status is changed or that is not a solution which happens instantly. If you use cronjob for indexing, that is not a fast solution again.You get server error until cronjob starts to work.
I would like to update solr index instantly for the attributes which changes frequently like price, status, etc. For instance, when an attribute changes, Is it a good way to start partial index immediately in java code? If it is, how? (by IndexerService?). For another solution, Is it a better idea to make http request to solr for the attribute?
In summary, I am looking for the best solution to perform partial index.
Any ideas?
For this case you need to write two new important SOLR-Configuration parts:
1) A new SOLR-Cronjob that trigger the indexing
2) A new SOLR-IndexerQuery for indexing with your special requirements.
When you have a look at the default stuff from hybris you see:
INSERT_UPDATE CronJob;code[unique=true];job(code);singleExecutable;sessionLanguage(isocode);active;
;backofficeSolrIndexerUpdateCronJob;backofficeSolrIndexerUpdateJob;false;en;false;
INSERT Trigger;cronJob(code);active;activationTime;year;month;day;hour;minute;second;relative;weekInterval;daysOfWeek;
;backofficeSolrIndexerUpdateCronJob;true;;-1;-1;-1;-1;-1;05;false;0;;
This part above is to configure when the job should run. You can modify him, that he should run ever 5 seconds for example.
INSERT_UPDATE SolrIndexerQuery; solrIndexedType(identifier)[unique = true]; identifier[unique = true]; type(code); injectCurrentDate[default = true]; injectCurrentTime[default = true]; injectLastIndexTime[default = true]; query; user(uid)
; $solrIndexedType ; $solrIndexedType-updateQuery ; update ; false ; false ; false ; "SELECT DISTINCT {PK} FROM {Product AS p JOIN VariantProduct AS vp ON {p.PK}={vp.baseProduct} } WHERE {p.modifiedtime} >= ?lastStartTimeWithSuccess OR {vp.modifiedtime} >= ?lastStartTimeWithSuccess" ; admin
The second part here is the more important. Here you define which products should be indexed. Here you can see that the UPDATE-Job is looking for every Product that was modified. Here you could write a new FlexibleSearch with your special requirements.
tl;tr Answear: You have to write a new performant solrIndexerQuery that could be trigger every 5 seconds
I am writing a java based REST API based on resteasy. I have following structure
Category has many groups; group has many preferences
I have 3 resources 1. category 2. group 3. preference
I want to support these API endpoints
/categories/{cat_id}/groups/ (returns all groups for the category)
/groups/{group_id}/preferences/ (returns all prefs for the group)
/preferences/{preference_id} (returns a pref identified by the id passed)
/preferences (returns all prefs)
I have 3 resource classes one for each resource mentioned above
I am confused how to structure the methods and where they should go. Following are my specific questions
/groups/{group_id}/preferences/ Should the implementation go under GroupsResourceImpl class or PreferenceResourceImpl class
PreferenceResourceImpl class has the implementation for /preferences end point which returns all the global preferences. So if /groups/{groupid}/preferences endpoint reside under GroupResource and call a method on the PreferenceResource (a method that takes in group id as an extra param) ??
Basically, the implementation makes no difference, you can do it either way. You should group them the way that groups the code the most logical way to you.
I, personally, like to group resource implementation the way that groups similar code together. This can be achieved by grouping together the paths that require similar ways to extract from the infrastructure. For example, if all your data is in relational database, then all your /*/preferences queries would be basically SELECT * FROM preferences WHERE ...different stuff.... Therefore, it would be most logical to group them all by the table you are querying from. For example:
GroupResource: /categories/{cat_id}/groups/
Because it would always query from table "groups": SELECT * FROM groups WHERE parent_cat_id = {cat_id}
PreferenceResource: /groups/{group_id}/preferences/, /preferences/{preference_id}, /preferences.
Because it would always query from table "preferences": SELECT * FROM preferences WHERE parent_group = {group_id}, ... WHERE id = {preference_id}, SELECT * FROM preferences
However, if your categories/groups/preferences reside in some kind of graph database - then to query /groups/{group_id}/preferences you would need to first find a group, and then get all the preferences from the inside and therefore, it would be more logical to group resources like this:
CategoryResource: /categories/{cat_id}/groups/
Because it would start querying from "categories" graph: categories.get(cat_id).getGroups()
GroupResource: /groups/{group_id}/preferences/
Because it would start querying from "groups" graph: groups.get(group_id).getPreferences()
PreferenceResource: , /preferences/{preference_id}, /preferences.
Because it would start querying from "preferences" graph: preferences.get(preference_id) and preferences.getAll()
Quick question... so in Hybris, I have a query similar to this:
"SELECT {CPR:pk} FROM {CategoryProductRelation as CPR}, ...."
Basically, I need to extract the Product Code and Category Code from Java which I think are available as source / target respectively but my question is, just like there's ProductModel, CategoryModel, etc. is there anything like that for CategoryProductRelation?, probably something like a generic RelationModel to simply extract source / target and go from there?
You'll need to JOIN in the entities like this
SELECT {CPR:pk}, {c.code} FROM {CategoryProductRelation as CPR
JOIN Category AS c on {CPR.source} = {c.PK} } WHERE ...
Also, you can do that in the Service Layer by simply calling your query and accessing the properties right from the relation type:
..
CategoryProductRelationModel model = result.get(0)
String categoryCode = ((CategoryModel)model.getSource()).getCode()
Depending on your amount of data, this could be pretty ineffecient.
Here's the deal:
public static List<Survey> getFilteredSurveys(Municipality municipality, Company company) {
String sql = "SELECT DISTINCT id FROM survey INNER JOIN " +
"(SELECT SURVEY_ID FROM publicity INNER JOIN brand "+
"ON publicity.brand_id=brand.id WHERE brand.company_id="+company.getId()+") "+
"ON survey_id=survey.id WHERE survey.municipality_id="+municipality.getId();
RawSql rawSql = RawSqlBuilder.parse(sql).create();
List<Survey> surveys = Ebean.find(Survey.class).setRawSql(rawSql).findList();
for (Survey survey : surveys) {
List<Publicity> publicities = new ArrayList<>();
for (Publicity publicity : survey.publicities) {
if(publicity.getBrand().getCompany() == company){
publicities.add(publicity);
}
}
survey.setPublicities(publicities);
}
return surveys;
}
This app is meant for measuring Publicities in a given place,
So people upload a 'Survey' of a place containing all the 'Publicity' that place has.
That function is supposed to return a List,
Each Survey has a List,
And each Publicity has a Brand, which is associated to a Company (ex. Coke -> Coca Cola Co.)
What I'm trying to do is this:
Given a Company, show all the surveys that contain a 'Coca Cola Co.' publicity, but showing only the publicities that belong to 'Coca Cola Co.'
I have a 'Surveys' controller which receives a form with a Municipality and a Company, calls this method, and it renders a view with its result.
This is part of the view template:
#(surveys: java.util.List[Survey])
#for(survey <- surveys){
#for(publicity <- survey.getPublicities){
<tr>
<td>#publicity.getBrand.getName</td>
<td>#publicity.getType.getName</td>
<td>#publicity.getSquareMeters</td>
</tr>
}
}
Problem: even though I removed some publicities from each Survey, all the publicities show up in the view. Why is this happening?
I know I'm not persisting the changes, and I don't want to, I just want to temporarily obfuscate the data so the user only sees the publicities that belong to a given company.
Why isn't this view using the surveys as they are given to it, modified?
Actually I'll put this in an answer ...
You should look at the SQL executed in the log (because I suspect you are getting N+1) here and you could fairly easily avoid that.
You should probably look to change your raw sql to include the publicities columns in the select clause (name, type, squareMeters) to avoid the extra queries.
Alternatively you could add fetch("publicities") to the query (so that they are fetched eagerly via a query join 100 at a time).
Also refer to:
https://github.com/ebean-orm/avaje-ebeanorm/issues/223
... RawSql that includes a OneToMany not working
https://github.com/ebean-orm/avaje-ebeanorm/issues/224
... Enhancement adding RawSqlBuilder.tableAliasMapping()
Ideally you'd be able to use 4.5.2 and take advantage of that fix and that enhancement.
So, I found a fix,
My fix was:
for (Survey survey : surveys) {
survey.getAddress(); //This line fixes the issue
List<Publicity> publicities = new ArrayList<>();
for (Publicity publicity : survey.publicities) {
if(publicity.getBrand().getCompany() != null){
if(publicity.getBrand().getCompany().getId().equals(company.getId())){
publicities.add(publicity);
}
}
}
survey.setPublicities(publicities);
}
My guess is that the problem resides in the way ebean lazily instantiates objects, despite setting Publicities to FetchType.EAGER, and the fact that the output from this function was the expected one, also inspecting surveys in the controller seemed to be ok, and also a #println(surveys) in the view showed only the publicities corresponding to the company I had selected.