What causes facet errors after Hibernate Search upgrade from version 4 to 5? - exception

Since upgrading (described below) the Facet search throws this exception.
HSEARCH000268: Facet request 'groupArchiv' tries to facet on field
'facetfieldarchiv' which either does not exists or is not configured
for faceting (via #Facet). Check your configuration.
Migrating from hibernate.search.version 4.4.4 to hibernate.search.version 5.5.2
lucene-queryparser 5.3.1
jdk 1.8xx
All the Indexing is via a ClassBridge.
The field facetfieldarchiv is in the index.
All other searches are working fine.
protected List<FacetBean> searchFacets(String searchQuery, String defaultField,
String onField, String facetGroupName)
{
List<FacetBean> results = new ArrayList<FacetBean>();
FullTextSession ftSession = getHibernateFulltextSession();
org.apache.lucene.analysis.Analyzer analyzer = getAnalyzer(Archiv.class);
QueryParser parser = new QueryParser(defaultField, analyzer);
try
{
Query query = parser.parse(searchQuery);
QueryBuilder builder = ftSession.getSearchFactory().buildQueryBuilder().forEntity(Item.class).get();
FacetingRequest gruppeFacetingRequest = builder.facet()
.name(facetGroupName)
.onField(onField).discrete()
.orderedBy(FacetSortOrder.COUNT_DESC)
.includeZeroCounts(false)
.maxFacetCount(99999)
.createFacetingRequest();
org.hibernate.search.FullTextQuery hibQuery = ftSession.createFullTextQuery(query, Item.class);
FacetManager facetManager = hibQuery.getFacetManager();
facetManager.enableFaceting(gruppeFacetingRequest);
Iterator<Facet> itf1 = facetManager.getFacets(facetGroupName).iterator();
**// The error occurs here,**
while (itf1.hasNext())
{
FacetBean bean = new FacetBean();
Facet facetgruppe = itf1.next();
bean.setFacetName(facetgruppe.getFacetingName());
bean.setFacetFieldName(facetgruppe.getFieldName());
bean.setFacetValue(facetgruppe.getValue());
bean.setFacetCount(facetgruppe.getCount());
results.add(bean);
}
} catch (Exception e)
{
logger.error(" Fehler FacetSuche: " + e);
}
return results;
}

The faceting API went through an overhaul between Hibernate Search 4 and 5. In the 4.x series one could facet on any (single valued) field without special configuration. The implementation was based on a custom Collector.
In Hibernate Search 5.x the implementation has changed and native Lucene faceting support is used. For this to work though, the faceted fields need to be known at index time. For this the annotation #Facet got introduced which needs to be places on fields used for faceting. You find more information in the Hibernate Search online docs or check this blog post which gives you a short summary of the changes.

Thank you for answering.
I didn't catch that change since 5.x
My facets are made up of several fields.
Is there a possibility to build the facets in a ClassBridge using pur Lucene?
like
FacetField f = new FacetField(fieldName, fieldValue);
document.add(f);
indexWriter.addDocument(document);
Thank you
pe

Related

RDF4J SPARQL query to JSON

I am trying to move data from a SPARQL endpoint to a JSONObject. Using RDF4J.
RDF4J documentation does not address this directly (some info about using endpoints, less about converting to JSON, and nothing where these two cases meet up).
Sofar I have:
SPARQLRepository repo = new SPARQLRepository(<My Endpoint>);
Map<String, String> headers = new HashMap<String, String>();
headers.put("Accept", "SPARQL/JSON");
repo.setAdditionalHttpHeaders(headers);
try (RepositoryConnection conn = repo.getConnection())
{
String queryString = "SELECT * WHERE {GRAPH <urn:x-evn-master:mwadata> {?s ?p ?o}}";
GraphQuery query = conn.prepareGraphQuery(queryString);
debug("Mark 2");
try (GraphQueryResult result = query.evaluate())
this fails because "Server responded with an unsupported file format: application/sparql-results+json"
I figured a SPARQLGraphQuery should take the place of GraphQuery, but RepositoryConnection does not have a relevant prepare statement.
If I exchange
try (RepositoryConnection conn = repo.getConnection())
with
try (SPARQLConnection conn = (SPARQLConnection)repo.getConnection())
I run into the problem that SPARQLConnection does not generate a SPARQLGraphQuery. The closest I can get is:
SPARQLGraphQuery query = (SPARQLGraphQuery)conn.prepareQuery(QueryLanguage.SPARQL, queryString);
which gives a runtime error as these types cannot be cast to eachother.
I do not know how to proceed from here. Any help or advise much appreciated. Thank you
this fails because "Server responded with an unsupported file format: application/sparql-results+json"
In RDF4J, SPARQL SELECT queries are tuple queries, so named because each result is a set of bindings, which are tuples of the form (name, value). In contrast, CONSTRUCT (and DESCRIBE) queries are graph queries, so called because their result is a graph, that is, a collection of RDF statements.
Furthermore, setting additional headers for the response format as you have done here is not necessary (except in rare circumstances), the RDF4J client handles this for you automatically, based on the registered set of parsers.
So, in short, simplify your code as follows:
SPARQLRepository repo = new SPARQLRepository(<My Endpoint>);
try (RepositoryConnection conn = repo.getConnection()) {
String queryString = "SELECT * WHERE {GRAPH <urn:x-evn-master:mwadata> {?s ?p ?o}}";
TupleQuery query = conn.prepareTupleQuery(queryString);
debug("Mark 2");
try (TupleQueryResult result = query.evaluate()) {
...
}
}
If you want to write the result of the query in JSON format, you could use a TupleQueryResultHandler, for example the SPARQLResultsJSONWriter, as follows:
SPARQLRepository repo = new SPARQLRepository(<My Endpoint>);
try (RepositoryConnection conn = repo.getConnection()) {
String queryString = "SELECT * WHERE {GRAPH <urn:x-evn-master:mwadata> {?s ?p ?o}}";
TupleQuery query = conn.prepareTupleQuery(queryString);
query.evaluate(new SPARQLResultsJSONWriter(System.out));
}
This will write the result of the query (in this example to standard output) using the SPARQL Query Results JSON format. If you have a non-standard format in mind, you could of course also create your own TupleQueryResultHandler implementation.
For more details on the various ways in which you can process the result (including iterating, streaming, adding to a List, or just directly sending to a result handler), see the documentation on querying a repository. As an aside, the javadoc on the RDF4J APIs is pretty extensive too, so if your Java editing environment has support for displaying that, I'd advise you to make use of it.

Springdata jpa and Native queries

I am doing a spring application and am kind stack. Iam running a query as shown below
#Autowired
EntityManagerFactory entityManagerFactory;
public List countTransactionsGroupByProvider(){
EntityManager em = entityManagerFactory.createEntityManager();
String query = "SELECT t.order_name,count(t.order_name) as number_of_transactions from transactions_view t where "
+ "t.transaction_date between '2014-07-24' and '2014-10-27' group by t.order_name";
List result = em.createNativeQuery(query).getResultList();
return result;
}
Now,This is working fine.it returns the data below:
[["Airtel",148], ["Expresso",8], ["Glo",49],
["MTN",110],["Select network",1],["Surfline",88],
["Tigo",35],["Vodafone",136],["Vouchers",30]]
My problem is I want this to return in the below format:
[{"order_name":"Airtel","number_of_transactions":148},
{"order_name":"Expresso","number_of_transactions":8},
{"order_name":"MTN","number_of_transactions":110},etc]
Then I can feed this into morris.js to plot a graph.
Any suggestion as to how to go about this.Thank much
You should probably just write some supporting code to transform the data into the format you want. Not sure you're going to get much traction trying to get JPA to produce the data in the format you want although it's arguably not out of the question.

Couchbase Custom Reduce behaving inconsistently

I am using couchbase version 2.0.1 - enterprise edition (build-170) and java-client version 1.2.2
I have a custom reduce function to get last activity of a user
The response from java client is inconsistent At time I get correct response and most of the time I get null value against valid keys. Even Stale.FALSE doesn't help !!
Number of records in view is around 1 millon and result set for query is arounk 1K key value pairs.
I am not sure what could be the issue here.. It will be great if someone can help.
Reduce Function is as below:
function (key, values, rereduce) {
var currDate = 0;
var activity = "";
for(var idx in values){
if(currDate < values[idx][0]){
currDate = values[idx][0];
activity = values[idx][1];
}
}
return [currDate, activity];
}
View Query:
CouchbaseClient cbc = Couchbase.getConnection();
Query query = new Query();
query.setIncludeDocs(false);
query.setSkip(0);
query.setLimit(10000);
query.setReduce(true);
query.setGroupLevel(4);
query.setRange(startKey,endKey);
View view = cbc.getView(document, view);
ViewResponse response = cbc.query(view, query);
Looks like There was some compatibility issue with java-client 1.2.2 and google gson 1.7.1 which was being used in my application. I switched to java-client 1.2.3 and google gson 2.2.4. Things are working as great now.

REST Web Service to consume MySQL DB

I'm building a REST WebService with JAX-RS and Tomcat to consume a MySQL Database.
I'm following this model:
#Path("/login")
public class Login {
String username;
String password;
// This method is called if POST is requested
#POST
#Produces(MediaType.APPLICATION_XML)
public String loginResponseXML(#FormParam("username") String user, #FormParam("password") String pass) {
//Connection to MySQL Database
try {
Class.forName("com.mysql.jdbc.Driver");
Connection con = DriverManager.getConnection("jdbc:mysql://localhost/sakila", "root","larcom");
Statement stmt = con.createStatement();
ResultSet rs = stmt.executeQuery("Select first_name, last_name From actor where first_name='" +
user + "' and last_name='" + pass + "'");
while (rs.next()){
System.out.println(rs.getString("first_name") + " " + rs.getString("last_name"));
username = rs.getString("first_name");
password = rs.getString("last_name");
}
}
catch (ClassNotFoundException e) {
e.printStackTrace();
} catch (SQLException e) {
e.printStackTrace();
}
if (user.equals(username) && pass.equals(password)) {
return ("<?xml version=\"1.0\"?>" + "<auth>200" + "</auth>"); //Success
//return "Success!";
} else {
return ("<?xml version=\"1.0\"?>" + "<auth>404" + "</auth>"); //Damn
//return "Damn!";
}
}
}
I call this method with:
HttpPost httppost = new HttpPost("http://192.168.15.245:8080/org.jersey.andre/rest/login");
Now, my question is:
If I want to query the DB for another table I have to create a new class like Login and make the JDBC connection again?
A new class and a new JDBC connection for each class that make a query to the DB? Performance issues?
Hope you can understand.
Thanks in advance.
A few tips are in order here: Please isolate the DB based code to a "data layer" so to speak...only perform dispatching/business logic within your resource classes.
Now If you are querying a different table, you WILL have a different query! You could either use the same connection (bad) or create a new one and fire a different query(s).
Now whether each resource hits a different table or the same table with a different query depends on your choice of 'representation' for that resource. There is a reason a RDB schema has multiple tables and it's quite common you'll have a different query involving multiple tables or to mutually independent tables.
Performance issues: For 'fresh data' you ARE always going to hit the DB so to speak. If you want to optimize that either develop your own cache (extremely hard) or use approaches like memcached or ehcache to boost performance - before you decide to do that make sure you verify if it's worth it.
Are you going to be having about 1000 DB hits per second? You probably need some performance boosting/handling. Per day...maybe not. Per 2-3 days...YAGNI (You ain't gonna need it, so don't worry for now)
So, for every 'resource' that you design in your application (Login is NOT a resource: See related post: Why is form based authentication NOT considered RESTful?) choose the representation. It may involve different queries etc., for you to return json/xml/xhtml (whatever you choose). Each 'DB related call' should be isolated into it's own 'data layer' - I suggest go with Spring JDBC to make your life easier. It'll take the burden of JDBC plumbing off your shoulders so you can focus on creating your DAOs (Data Access Objects - a patter for Data Access classes. All DAOs logically belong in the data layer)
Hope this helps

Issue using NHibernate SchemaUpdate with MySQL - no error, but nothing happens!

I've been having some issues using SchemaUpdate with MySQL.
I seem to have implemented everything correctly, but when I run it
it doesn't update anything. It doesn't generate any errors, and it
pauses for about the sort of length of time you would expect it to
take to inspect the DB schema, but it simply doesn't update anything,
and when I try to get it to script the change it just doesn't do
anything - it's as if it can;'t detect any changes to up the DB
schema, but I have created a new entity and a new mapping class - so I
cant see why it's not picking it up.
var config = Fluently.Configure()
.Database(() => {
var dbConfig = MySQLConfiguration.Standard.ConnectionString(
c => c.Server(configuration.Get<string>("server", ""))
.Database(configuration.Get<string>("database",""))
.Password(configuration.Get<string>("password", ""))
.Username(configuration.Get<string>("user", ""))
);
});
config.Mappings(
m => m.FluentMappings
.AddFromAssemblyOf<User>()
.AddFromAssemblyOf<UserMap>()
.Conventions.AddFromAssemblyOf<UserMap>()
.Conventions.AddFromAssemblyOf<PrimaryKeyIdConvention>()
// .PersistenceModel.Add(new CultureFilter())
);
var export = new SchemaUpdate(config);
export.Execute(false, true);
I don't think there's anything wrong with my config because it works
perfectly well with ShemaExport - it's just SchemaUpdate where I seem
to have a problem.
any ideas would be much appreciated!
Did you try to wrap SchemaUpdate execution in a transaction? There're some databases which need to run this in a transaction AFAIK.
using (var tx = session.BeginTransaction())
{
var tempFileName = Path.GetTempFileName();
try
{
using (var str = new StreamWriter(tempFileName))
{
new SchemaExport(configuration).Execute(showBuildScript, true, false, session.Connection, str);
}
}
finally
{
if (File.Exists(tempFileName))
{
File.Delete(tempFileName);
}
}
tx.Commit();
}
I figured it out:
The problem is that MySQL doesn't have multiple databases. It seems like some parts of MySQL and/or NHibernate use Schemas instead and SchemaUpdate seems to be one of them. So when I have
Database=A
in my connectionstring, and
<class ... schema="B">
in the mapping, then SchemaUpdate seems to think that this class is "for a different database" and doesn't update it.
The only fix I can think of right now would be to do a SchemaUpdate for every single schema (calling USE schema; first). But afaik, NHibernate has no interface to get a list of all schemas that are used in the mappings (correct me if I'm wrong). I'm afraid I have to iterate through the XML files manually (I use XML-based mappings) and collect them...