Virtuoso Jena Provider Construct Query Error - java

My problem is similar to the one asked on this question:
Is there a differense between a CONSTRUCT queries sent to a virtuoso endpoint and one sent to a Jena one?
I am using Virtuoso opensource as my graphstore and using the jena provider in order to access the data in that graphstore. I am doing several querys and everything is working fine (except for the amazing amount of memory and time that takes every inference with virtuoso but that should go in another question...).
The problem came when I tried to generate a model using a construct query. I have try using the VirtuosoQueryExecutionFactory and the query as string and the default QueryExecutionFactory with the query factory:
qexec = VirtuosoQueryExecutionFactory.create(queryString,inputModel);
model = qexec.execConstruct();
And
Query query = QueryFactory.create(queryString);
qexec = QueryExecutionFactory.create(query,inputModel);
model = qexec.execConstruct();
The query gives the expected result in the sparql endpoint but an empty model when querying in the code.
LOGGER.info("The model is: {}", model);
LOGGER.info("The size is: {}", model.size());
Gives the following output:
The model is: <ModelCom {} | >
The size is: 0
The model where I execute the querys is not empty and I did the same query from the sparql endpoint, as I said, recieving the spected results.
Anyone know where could be the mistake?
Thanks.
Daniel.
EDIT:
Here is the query I am trying to execute.
PREFIX rdf:<http://www.w3.org/1999/02/22-rdf-syntax-ns#>
PREFIX rdfs:<http://www.w3.org/2000/01/rdf-schema#>
PREFIX owl:<http://www.w3.org/2002/07/owl#>
PREFIX xsd:<http://www.w3.org/2001/XMLSchema#>
PREFIX spatiaCore:<http://www.cedint.upm.es/residentialontology.owl#>
PREFIX test:<http://test.url#>
PREFIX spatiaCore: <http://www.cedint.upm.es/residentialontology.owl#>
CONSTRUCT {
?u ?p ?o1.
?o1 ?p2 ?o2.
?o2 ?p3 ?o3.
?o3 ?p4 ?o4.
?o4 ?p5 ?o5.
?o6 ?p6 ?u.
?o7 ?p7 ?o6
}
WHERE {
?u rdf:type spatiaCore:User.
?u spatiaCore:id "0000000003B3B474"^^<http://www.w3.org/2001/XMLSchema#string>.
?u ?p ?o1.
OPTIONAL {
?o1 ?p2 ?o2.
OPTIONAL {
?o2 ?p3 ?o3.
OPTIONAL {
?o3 ?p4 ?o4.
OPTIONAL {
?o4 ?p5 ?o5.
}
}
}
}
OPTIONAL {
?o6 ?p6 ?u.
OPTIONAL {
?o7 ?p7 ?o6
}
}
}
As you can see, the query tries to construct a graph with all the nodes the user is linked to with a depth of max five relationships and the nodes that are linked to the user with a depth of max two relationships.

What kind of method did you use for create VirtModel object?
NOTE:
If you used:
public static VirtModel openDefaultModel(DataSource ds);
public static VirtModel openDefaultModel(String url, String user, String password);
so the Model will contains only data from "virt:DEFAULT" graph.
And VirtuosoQueryExecutionFactory will add next pragma to query text:
define input:default-graph-uri <virt:DEFAULT>
If you used something like:
public static VirtModel openDatabaseModel(String graphName, DataSource ds);
public static VirtModel openDatabaseModel(String graphName, String url, String user, String password)
so the Model will contains only data from graphName graph.
And VirtuosoQueryExecutionFactory will add next pragma to query text:
define input:default-graph-uri <graphName>
If you want to use data from all graphs, you must call:
VirtModel vmodel = ....create model method...
vmodel.setReadFromAllGraphs(true);
If you set above to TRUE, the pragma for default-graph-uri will not added.
The worked example of using Construct with Virtuoso Jena provider:
url = "jdbc:virtuoso://localhost:1111";
VirtGraph set = new VirtGraph ("test1", url, "dba", "dba");
set.clear();
String qry = "INSERT INTO GRAPH <test1> { <aa> <bb> 'cc' . <aa1> <bb> 'zz' }";
VirtuosoUpdateRequest vur = VirtuosoUpdateFactory.create(qry, set);
vur.exec();
Model inputModel = new VirtModel(set);
System.out.println("InputModel :"+inputModel);
System.out.println("InputModel size :"+inputModel.size());
System.out.println();
qry = "CONSTRUCT { ?x <a> ?y } WHERE { ?x <bb> ?y }";
QueryExecution vqe = VirtuosoQueryExecutionFactory.create (qry, inputModel);
Model model = vqe.execConstruct();
System.out.println("Model :"+model);
System.out.println("Model size :"+model.size());

Related

how to save modification (creation ,update of OWL file) into fuseki server

I created an ontology model using protege. ,
I used java to populate my ontology( reate user , resources..)
and then I save all modification into a file.
Now I need to integrate an RDF server to save changes
after some research I found that Fuseki is one of the best servers that I can use ..
After some more research I also found that I need to use RDFCOnnexion to communicate with the fuseki server but I am having some difficulties with integrating the server and manipulating all of my Java classes.
To request my ontology , I used RDFconnexion:
example :
public static void main(String[] args) {
RDFConnection conn1 =
RDFConnectionFactory.connect("http://localhost:3030/test/") ;
try( QueryExecution qExec = conn1.query("PREFIX ex: <http://example.org/>
SELECT * { ?s ?p ?o }") ) {
ResultSet rs = qExec.execSelect();
ResultSetFormatter.out(rs, qExec.getQuery());
}
}
but I am running into issues trying to create the Agent (user) ,or resource..
below you will find just a part of my Java code :
private final OntModel onto;
private OntModel inferred;
public test() {
onto = ModelFactory.createOntologyModel(OntModelSpec.OWL_MEM);
OntDocumentManager manager = onto.getDocumentManager();
manager.addAltEntry("http://www-test/1.0.0", "ontologies/test.owl");
}
public String createUri(String prefix, String localName){
String uri = prefix + "#" + localName ;
uri = uri.replaceAll(" ", "_") ;
return uri ;
}
// to create Agent
public Resource createAgent(String uri) throws
AlreadyExistingRdfResourceException {
Resource agent = this.createEntity(uri) ;
if (agent==null) return null ;
Property prop ; Statement s ;
s = ResourceFactory.createStatement(agent, RDF.type,
onto.getIndividual(EngineConstants.CD_Agent)) ;
onto.add(s) ;
this.synchronize();
return agent ;
}
// TO get Agent Activty
public Set<Resource> getAgentActivities(String agentUri){
final String query = "SELECT ?entity WHERE { ?entity CD:hasAgent <"+
agentUri +">}" ;
ResultSet resultSet = this.queryExec(this.getInferred(), query);
return this.getRdfResources(resultSet, "entity") ;
}
I need to know if someone can help me and give me an example how I can use and integrate Fuseki to ( modify and request my ontology).
thank you for your help
Note you probably first want to retrieve your graph using the fetch() method - http://jena.apache.org/documentation/javadoc/rdfconnection/org/apache/jena/rdfconnection/RDFDatasetAccessConnection.html#fetch-java.lang.String- - which will be more efficient than querying for it as you do now e.g.
Model model = connection.fetch("http://your-graph-name");
If you are just using the default graph you can just do connection.fetch() to retrieve that.
Once you have the local copy modify it with Jena APIs as you desire.
You can then use the put() method to update a graph - http://jena.apache.org/documentation/javadoc/rdfconnection/org/apache/jena/rdfconnection/RDFConnection.html#put-java.lang.String-org.apache.jena.rdf.model.Model- - with your local changes e.g.
connection.put("http://your-graph-name", model);
This will overwrite the existing graph with the current contents of model. Again if you are just using the default graph you can just do connection.put(model).

Search users under organization in Liferay

I have to search users under the specific organization in liferay. At present we have a search available with
UserLocalService.search()
which is based on the companyId . I was wondering if there is any otherway even using the DynamicQueryFactoryUtil do fetch along with organization filter.
The dynamic query looks good, but I found an another way. We can pass the organization id using Map.
params.put("usersOrgs", orgId);
List<User> searchResult = liferayUserLocalService.search(companyId, keyword, WorkflowConstants.STATUS_APPROVED, params, 0, -1, "");
which will filter the users based on organization.
Of Course You can use DynamicQuery for achieving this.
This can be done in two phase ,
Fetch User Id associated with the given Organization.
Use search criterion along with the id received in first phase.
So, the code will look as following ,
// Fetch userId List form Organization id
long[] organiztionIds = UserLocalServiceUtil.getOrganizationUserIds(orgId);
DynamicQuery searchQuery = DynamicQueryFactoryUtil.forClass(User.class, UserLocalServiceUtil.class.getClassLoader());
Criterion searchCriteria = PropertyFactoryUtil.forName("companyId").eq(companyid);
//Add Organization Id in Criterion
if (organiztionIds.length != 0) {
searchCriteria =
RestrictionsFactoryUtil.and(RestrictionsFactoryUtil.in("userId", ArrayUtils.toObject(organiztionIds)), searchCriteria);
}
if (!firstName.isEmpty()) {
searchCriteria = RestrictionsFactoryUtil.or(RestrictionsFactoryUtil.eq("firstName", firstName), searchCriteria);
}
if (!middleName.isEmpty()) {
searchCriteria = RestrictionsFactoryUtil.or(RestrictionsFactoryUtil.eq("middleName", middleName), searchCriteria);
}
if (!lastName.isEmpty()) {
searchCriteria = RestrictionsFactoryUtil.or(RestrictionsFactoryUtil.eq("lastName", lastName), searchCriteria);
}
if (!screenName.isEmpty()) {
searchCriteria = RestrictionsFactoryUtil.or(RestrictionsFactoryUtil.eq("screenName", screenName), searchCriteria);
}
searchQuery.add(searchCriteria);
UserLocalServiceUtil.dynamicQuery(searchQuery);
P.S
I haven't tested this code. But this is the way to do it.
I Hope it helps you.

MarkLogic - Sorting Query By Example Search

....
StringHandle rawHandle = new StringHandle(jsonString);
RawQueryByExampleDefinition querydef = queryManager.newRawQueryByExampleDefinition(rawHandle);
querydef.setCollections(collection);
StringHandle report = queryManager.validate(querydef, new StringHandle());
LOGGER.info("Query Def valididity: {}",report.toString());
StringHandle resultsHandle = new StringHandle().withFormat(Format.JSON);
queryManager.setPageLength(size);
queryManager.search(querydef, resultsHandle, startIndex);
....
I'm using the code above for MarkLogic search Query By Example, my question is how could you pass in a "sort by" criteria into the RawQueryByExampleDefinition to sort or order the resultset. For example I want the result to be sorted by emailAddress similar to the below query:
{
"$query":
{
"identifier":"user",
"$sort-by":"emailAddress"
}
}
How do I achieve the "sortby" as well as specifying desc or asc?
I think that would be done using a "combined query" from https://docs.marklogic.com/guide/java/searches#id_76144 with the sort-order option from https://docs.marklogic.com/search:search

Grouping Solr results in Solr 3.6.1 API causes NullPointerException when parsing result

As long as I limit my query to:
SolrQuery solrQuery = new SolrQuery();
solrQuery.set("q", query); //where query is solr query string (e.g. *:*)
solrQuery.set("start", 0);
solrQuery.set("rows", 10);
everything works fine - results are returned and so on.
Things are getting worse when I try to group results by my field "Token_group" to avoid duplicates:
SolrQuery solrQuery = new SolrQuery();
solrQuery.set("q", query); //where query is solr query string (e.g. *:*)
solrQuery.set("start", 0);
solrQuery.set("rows", 10);
solrQuery.set("group", true);
solrQuery.set("group.field", "token_group");
solrQuery.set("group.ngroups", true);
solrQuery.set("group.limit", 20);
Using this results in HttpSolrServer no exceptions are being thrown, but trying to access results ends up in NPE.
My querying Solr method:
public SolrDocumentList query(SolrQuery query) throws SolrServerException {
QueryResponse response = this.solr.query(query); //(this.solr is handle to HttpSolrSelver)
SolrDocumentList list = response.getResults();
return list;
}
note that similar grouping (using the very same field) is made in our other apps (PHP) and works fine, so this is not a schema issue.
I solved my issue. In case someone needs this in future:
When you perform a group query, you should use different methods to get and parse results.
While in ungrouped queries
QueryResponse response = this.solr.query(query); //(this.solr is handle to HttpSolrSelver)
SolrDocumentList list = response.getResults();
will work, when you want to query for groups, it won't.
So, how do I make and parse query?
Below code for building query is perfectly fine:
SolrQuery solrQuery = new SolrQuery();
solrQuery.set("q", query); //where query is solr query string (e.g. *:*)
solrQuery.set("start", 0);
solrQuery.set("rows", 10);
solrQuery.set("group", true);
solrQuery.set("group.field", "token_group");
solrQuery.set("group.ngroups", true);
solrQuery.set("group.limit", 20);
where last four lines define that Solr should group results and parameters of grouping. In this case group.limit will define how many maximum results within a group you want, and rows will tell how many max results should be there.
Making grouped query looks like this:
List<GroupCommand> groupCommands = this.solr.query(query).getGroupResponse().getValues();
referring to documentation, GroupCommand contains info about grouping as well as list of results, divided by groups.
Okay, I want to get to the results. How to do it?
Well, in my example there's only one position in List<GroupCommand> groupCommands, so to get list of found groups within it:
GroupCommand groupCommand = groupCommands.get(0);
List<Group> groups = groupCommand.getValues();
This will result in list of groups. Each group contains its own SolrDocumentList. To get it:
for(Group g : groups){
SolrDocumentList groupList = g.getResult();
(...)
}
Having this, well just proceed with SolrDocumentList for each group.
I used grouping query to get list of distinct results. How to do it?
This was exacly my case. It seems easy but there's a tricky part that can catch you if you're refactoring already running code that uses getNumFound() from SolrDocumentList.
Just analyze my code:
/**
* Gets distinct resultlist from grouped query
*
* #param query
* #return results list
* #throws SolrServerException
*/
public SolrDocumentList queryGrouped(SolrQuery query) throws SolrServerException {
List<GroupCommand> groupCommands = this.solr.query(query).getGroupResponse().getValues();
GroupCommand groupCommand = groupCommands.get(0);
List<Group> groups = groupCommand.getValues();
SolrDocumentList list = new SolrDocumentList();
if(groups.size() > 0){
long totalNumFound = groupCommand.getNGroups();
int iteratorLimit = 1;
for(Group g : groups){
SolrDocumentList groupList = g.getResult();
list.add(groupList.get(0));
//I wanted to limit list to 10 records
if(iteratorLimit++ > 10){
break;
}
}
list.setNumFound(totalNumFound);
}
return list;
}

MongoTemplate upsert - easy way to make Update from pojo (which user has editted)?

Here is a simple pojo:
public class Description {
private String code;
private String name;
private String norwegian;
private String english;
}
And please see the following code to apply an upsert to MongoDb via spring MongoTemplate:
Query query = new Query(Criteria.where("code").is(description.getCode()));
Update update = new Update().set("name", description.getName()).set("norwegian", description.getNorwegian()).set("english", description.getEnglish());
mongoTemplate.upsert(query, update, "descriptions");
The line to generate the Update object specifies every field of the Item class manually.
But if my Item object changes then my Dao layer breaks.
So is there a way to avoid doing this, so that all fields from my Item class are applied automatically to the update?
E.g.
Update update = new Update().fromObject(item);
Note that my pojo does not extend DBObject.
I found a pretty good solution for this question
//make a new description here
Description d = new Description();
d.setCode("no");
d.setName("norwegian");
d.setNorwegian("norwegian");
d.setEnglish("english");
//build query
Query query = new Query(Criteria.where("code").is(description.getCode()));
//build update
DBObject dbDoc = new BasicDBObject();
mongoTemplate.getConverter().write(d, dbDoc); //it is the one spring use for convertions.
Update update = Update.fromDBObject(dbDoc);
//run it!
mongoTemplate.upsert(query, update, "descriptions");
Plz note that Update.fromDBObject return an update object with all fields in dbDoc. If you just want to update non-null fields, you should code a new method to exclude null fields.
For example, the front-end post a doc like below:
//make a new description here
Description d = new Description();
d.setCode("no");
d.setEnglish("norwegian");
We only need to update the field 'language':
//return Update object
public static Update fromDBObjectExcludeNullFields(DBObject object) {
Update update = new Update();
for (String key : object.keySet()) {
Object value = object.get(key);
if(value!=null){
update.set(key, value);
}
}
return update;
}
//build udpate
Update update = fromDBObjectExcludeNullFields(dbDoc);
The solution for a new spring-data-mongodb version 2.X.X.
The API has evolved, since 2.X.X version there is:
Update.fromDocument(org.bson.Document object, String... exclude)
instead of (1.X.X):
Update.fromDBObject(com.mongodb.DBObject object, String... exclude)
The full solution:
//make a new description here
Description d = new Description();
d.setCode("no");
d.setName("norwegian");
d.setNorwegian("norwegian");
d.setEnglish("english");
Query query = new Query(Criteria.where("code").is(description.getCode()));
Document doc = new Document(); // org.bson.Document
mongoTemplate.getConverter().write(item, doc);
Update update = Update.fromDocument(doc);
mongoTemplate.upsert(query, update, "descriptions");
It works!
you can use save : (if non exist = insert else = upsert)
save(Object objectToSave, String collectionName)
read : javadoc
Just like previous answers said, use mongoTemplate.getConverter().write() and Update.fromDocument() functions. But i found Update.fromDocument() won't add "$set" key and won't work directly, the solution is to add "$set" yourself, like below (PS: I'm using 2.2.1.RELEASE version):
public static Update updateFromObject(Object object, MongoTemplate mongoTemplate) {
Document doc = new Document();
mongoTemplate.getConverter().write(object, doc);
return Update.fromDocument(new Document("$set", doc));
}
If you want to upsert Pojos incl. property String id; you have to exclude the _id field in the fromDBObject method Update.fromDBObject(dbDoc,"_id").
Otherwise you get the Exception:
org.springframework.dao.DuplicateKeyException: { "serverUsed" : "127.0.0.1:27017" , "ok" : 1 , "n" : 0 , "updatedExisting" : false , "err" : "E11000 duplicate key error collection: db.description index: _id_ dup key: { : null }" , "code" : 11000}; nested exception is com.mongodb.MongoException$DuplicateKey: { "serverUsed" : "127.0.0.1:27017" , "ok" : 1 , "n" : 0 , "updatedExisting" : false , "err" : "E11000 duplicate key error collection: db.description index: _id_ dup key: { : null }" , "code" : 11000}
because the _id field of the first is null
{
"_id" : null,
...
}
Fullcode based on #PaniniGelato answer would be
public class Description(){
public String id;
...
}
Description d = new Description();
d.setCode("no");
d.setName("norwegian");
d.setNorwegian("norwegian");
d.setEnglish("english");
//build query
Query query = new Query(Criteria.where("code").is(description.getCode()));
//build update
DBObject dbDoc = new BasicDBObject();
mongoTemplate.getConverter().write(d, dbDoc); //it is the one spring use for convertions.
Update update = Update.fromDBObject(dbDoc, "_id");
//run it!
mongoTemplate.upsert(query, update, "descriptions");
Then the upsert is working in the cases of insert and update. Corrections & thoughts are welcome ;)
This is what I am doing for the time being. Not so much elegant way to do it, but it does save a precious DB call:
import org.springframework.data.mongodb.core.MongoTemplate;
import org.springframework.data.mongodb.core.query.Query;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.mongodb.BasicDBObject;
import com.mongodb.DB;
import com.mongodb.DBCollection;
import com.mongodb.DBObject;
import com.mongodb.util.JSON;
/**
* Perform an upsert operation to update ALL FIELDS in an object using native mongo driver's methods
* since mongoTemplate's upsert method doesn't allow it
* #param upsertQuery
* #param object
* #param collectionName
*/
private void performUpsert(Query upsertQuery, Object object, String collectionName){
ObjectMapper mapper = new ObjectMapper();
try {
String jsonStr = mapper.writeValueAsString(object);
DB db = mongoTemplate.getDb();
DBCollection collection = db.getCollection(collectionName);
DBObject query = upsertQuery.getQueryObject();
DBObject update = new BasicDBObject("$set", JSON.parse(jsonStr));
collection.update(query, update, true, false);
} catch (IOException e) {
LOGGER.error("Unable to persist the metrics in DB. Error while parsing object: {}", e);
}
}
There are two cases here that need to be distinguished:
Update an item that was previously fetched from the DB.
Update or insert (upsert) an item you created by code.
In Case 1) You can simply use mongoTemplate.save(pojo, "collection"), because your POJO will already have a filled ObjectID in its id field.
In case 2) You have to explain to mongo what "already exists" means in case of your domain model: By default the mongoTemplate.save() method updates an existing item, if there is one with that same ObjectId. But with a newly instantiated POJO you do not have that id. Therefore the mongoTemplate.upsert() method has a query parameter that you can create like this:
MyDomainClass pojo = new MyDomainClass(...);
Query query = Query.query(Criteria.where("email").is("user1#domain.com"));
DBObject dbDoc = new BasicDBObject();
mongoTemplate.getConverter().write(pojo, dbDoc); //it is the one spring use for convertions.
dbDoc.removeField("_id"); // just to be sure to not create any duplicates
Update update = Update.fromDBObject(dbDoc);
WriteResult writeResult = mongoTemplate.upsert(query, update, UserModel.class);
I ran into the same problem. In het current Spring Data MongoDB version no such thing is available. You have to update the seperate fields by hand.
However it is possible with another framework: Morphia.
This framework has a wrapper for DAO functionality: https://github.com/mongodb/morphia/wiki/DAOSupport
You can use the DAO API to do things like this:
SomePojo pojo = daoInstance.findOne("some-field", "some-value");
pojo.setAProperty("changing this property");
daoInstance.save(pojo);
I think that:
Description add a property
#Id
private String id;
then get a document by the query condition,set Description's id by document's id.
and save
Just use ReflectionDBObject - if you make Description extend it, you should just get your object's fields transferred to Update reflectively, automagically. The note from above about null fields included in the update still holds true.
public void saveOrUpdate(String json) {
try {
JSONObject jsonObject = new JSONObject(json);
DBObject update1 = new BasicDBObject("$set", JSON.parse(json));
mongoTemplate.getCollection("collectionName").update(new Query(Criteria.where("name").is(jsonObject.getString("name"))).getQueryObject(), update1, true, false);
} catch (Exception e) {
throw new GenericServiceException("Error while save/udpate. Error msg: " + e.getMessage(), e);
}
}
this is very simple way to save json string into collection using mongodb
and spring.
This method can be override to use as JSONObject.
#Override
public void updateInfo(UpdateObject algorithm) {
Document document = new Document();
mongoTemplate.getConverter().write(algorithm, document);
Update update = Update.fromDocument(document);
mongoTemplate.updateFirst(query(where("_id").is(algorithm.get_id())), update, UpdateObject.class);
}
After upsert, I was Tring to fetch same record but it was given me the old one.
But in dB I am having new records.

Categories