I am trying to create a hibernate full text search using hibernate-search-4.3.0.Final.jar
There is no errors in this application, but my Lucene query unsing the query DSL doesn't return any results.
I mean It doesn't return any of rows in the table. can any one please help me.
This is my function:
OgmConfiguration cfgogm=new OgmConfiguration();
cfgogm.configure("hibernate.cfg.xml");
serviceregistry=new ServiceRegistryBuilder().applySettings(cfgogm.getProperties()).buildServiceRegistry();
sessionfactory=cfgogm.buildSessionFactory(serviceregistry);
Session session= sessionfactory.openSession();
FullTextSession fulltextsession= Search.getFullTextSession(session);
QueryBuilder querybuilder=fulltextsession.getSearchFactory().buildQueryBuilder().forEntity(User.class).get();
org.apache.lucene.search.Query lucenequery=querybuilder.keyword().onField("IdU").matching("96645").createQuery();
org.hibernate.search.FullTextQuery fulltextquery=fulltextsession.createFullTextQuery(lucenequery, User.class);
List result=fulltextquery.list();
System.out.println(result.toString());
and this is my POJO class:
#Entity
#Table(name="Users")
#Indexed
public class User {
#Id
#GeneratedValue(generator="mongodb_uuidgg")
#Field(index = Index.YES,analyze = Analyze.NO,store = Store.NO)
private String _id;
#Column(name="City")
#Field(index = Index.YES,analyze = Analyze.NO,store = Store.NO)
private String city;
#Column(name="UserID")
#Field(index = Index.YES,analyze = Analyze.NO,store = Store.NO)
private int IdU;
...
I would use Luke to verify that your queries actually return what you want from the index.
[edit...]
If Luke shows that the index is empty, you will need to look at your indexing setup.
Most likely, the configuration for the id field is incorrect. It should be:
#Id
#GeneratedValue(generator="mongodb_uuidgg")
#DocumentId
private String _id;
(i.e. #DocumentId instead of #Field).
Have you actually indexed the data? You need to create the initial index, if you start with an existing database. You can use the programmatic index API and the mass indexer to create the initial index. Once you have the initial index and you are you use incremental indexing the index will stay in sync with database changes (provided changes are made via the Hibernate/JPA API).
Other than that have look at the lg file. Is there anything in there? If you still have the issue please post the code you use to index the data.
Related
I am new to MongoDB and have trouble. I would be very grateful if someone could help me with it.
I have the entity like:
class FileRecord {
private ObjectId id;
private String fileId;
private EnumStatus status;
private Long userId;
private Integer year;
etc.
> }
A file can have many records but only one in the year.
I need to get all the last documents by criteria.
I don't understand how to make it right in Spring, but in the mongo query too if to be honest)
I understand how to make criteria for it:
var match = match(Criteria.where("userId").in(userIds).andOperator(Criteria.where("status").in(EnumStatus.availableStatues())));
And group by max:
var group = group("fileId", "year").max("year").as("max_year");
But how to make it to query in one that will return for me Colletion<FileRecord> after aggregation?
If I try it make it this way:
var aggregation = newAggregation(filter, group);
AggregationResults<FileRecord> aggregateResult =
mongoOperations.aggregate(aggregation, FileRecord.class, FileRecord.class);
Collection<FileRecord> records = aggregateResult.getMappedResults()
I get an exception:
readObjectId can only be called when CurrentBSONType is OBJECT_ID, not when CurrentBSONType is DOCUMENT.;
If someone has an idea I'm interested
Thank you in advance
I found the answer)
var group = group("fileId", "year").max("year").as("max_year").first("_id").as("enityId");
I needed to create the projection and after again make request to the DB and get the data that I needed by id. I don't have many of them, so the solution worked for me. But, as I understand, you can add a lot "first", and add the fields you need. And get all by one request
I want an entity class through which I can store data to DB, for
specific columns I want in case-sensitive, is there any annotation to
be used above these specific columns to store as requested? please let
me if the question is not clear,Thanks in advance.
#Column(name = "EMAIL",unique=true) //i want store this email id as lower case,
private String email; //never mind in what case user enters
You can do this using #ColumnTransformer
#Column(name = "email")
#ColumnTransformer(write = "LOWER(email)")
private String email;
I try this and it works:
#Column
#ColumnTransformer(write = "LOWER(?)")
private String email;
expression of #ColumnTransformer.write would replace the original "?" placeholder in persisting sql statement. So must provide a compliant-sql expression with "?":
insert into member (email) values (?)
---->
insert into member (email) values (LOWER(?))
detail usage: https://docs.jboss.org/hibernate/orm/5.4/javadocs/org/hibernate/annotations/ColumnTransformer.html
I have a kind named Posts and the key is postId.
The postId format is : YYMMDDXXX. Where XXX is 3 digits sequence number.
For example : 150703001, 150704001, 150704002
How do I get the sequence number from my entities in datastore? I want to convert this SQL Select nvl(max(substring(postId, 7, 3)), 0) from posts where substring(postId, 1, 6) = '150704' to Objectivy filter.
Please help, thanks a lot!
You will have to re-design your Kinds/Entities into a different structure to accomplish this. The datastore can not search by substring.
A possible approach could be this layout :
#Entity
class PostGroup {
#Id
String id; // this is will hold the formatted date YYMMDD
}
#Entity
class Post {
#Id
Long id; // auto generated ID
#Index
Long sequence; // the sequence number
#Parent
Key<PostGroup> group;
}
Now you can set the PostGroup has the ancestor for your Objectify query, sort by Post.sequence desc limit 1 to find the latest post.
String yymmdd = "150704";
Key<PostGroup> postGroupKey = Key.create(PostGroup.class, yymmdd);
Query<Post> query = ofy().type(Post.class).ancestor(postGroupKey).order("-sequence");
Post latestPost = query.first().now();
Note: you don't have to actually persist the PostGroups to use them as ancestors.
Here is how I'm getting my User beans from Database.
session.createCriteria(User.class).list();
That returns all of User records from database. Interesting part is that, I don't want to get the password field from DB. Just want to exclude that field while retrieving.
Options I have
1) using projections on other fields. That needs to be more code to add in to projections list. So dropped from that idea.
2) With Sql I need to write a manually query, which kills the theme of Hibernate.
Any possibility to exclude a column value of Bean ?
you can try:
Example example = Example.create(cat)
.excludeZeroes() //exclude zero valued properties
.excludeProperty("color") //exclude the property named "color"
.ignoreCase() //perform case insensitive string comparisons
.enableLike(); //use like for string comparisons
List results = session.createCriteria(Cat.class)
.add(example)
.list();
Reference :-
http://docs.jboss.org/hibernate/orm/3.6/reference/en-US/html/querycriteria.html#querycriteria-examples
http://docs.jboss.org/hibernate/orm/3.6/javadocs/org/hibernate/criterion/Example.html
Let's assume that following is your POJO:
User.java
private long id;
private String fName;
private String lName;
// getter - setter of all fields
Now suppose you want to get only id & fName fields and not lName.
Apart from the two approaches you've described, there's also a third way to achieve this, which uses HQL.
Query q1 = session.createQuery("Select new User(id, fName) from User");
List<User> users = q1.list();
Modify User.java to have another constructor as follows:
public User(long id, String fName)
{
this.id = id;
this.fName = fName;
}
In short, whatever fields you want to retrieve, you can list them in the constructor as well as in the query.
Hope this helps.
Let's say I have the following two classes; User and Location. I want to create a DetachedCriteria to query the user table, and return all users who do not have a location with the name "xyz".
#Entity
public class User {
#Id
#GeneratedValue(strategy = GenerationType.AUTO)
Long id;
#CollectionOfElements
Set<Location> locations;
}
#Entity
public class Location{
#Id
#GeneratedValue(strategy = GenerationType.AUTO)
Long id;
#Column
String name;
}
The following code will return all users who DO have a location with name "xyz" set:
DetachedCriteria dc = DetachedCriteria.forClass(User.class);
dc.createCriteria("locations")
dc.add(Restrictions.eq("name", "xyz"));
If I change to Restrictions.ne(), that doesn't work, because it will only return users who actually have locations set. Also, if there are a bunch of locations set for a user, it will duplicate that user over and over.
Any ideas?
Using the entities User and Location as described in your original post:
1) Check if the associated locations is empty.
Junction or = Restrictions.disjunction();
or.add(Restrictions.isEmpty("locations"));
2) Create an associated criteria for locations using a LEFT_JOIN and an alias to be used in the "ne" restriction. The LEFT_JOIN is required so we still get User records back even if the locations relationship is empty.
userCriteria.createCriteria("locations", "loc", Criteria.LEFT_JOIN);
or.add(Restrictions.ne("loc.name", "xyz"));
3) Add the disjunction to the the original User criteria.
userCriteria.add(or);
You'll probably need to use some combination of Restrictions.and(), Restrictions.not(), Restrictions.or() and Restrictions.in() to get your inverse-logic to work right. Check http://docs.jboss.org/hibernate/core/3.5/api/org/hibernate/criterion/Restrictions.html - it can definitely be done!
To ensure you only get at-most-one User, use a Distinct projection (http://docs.jboss.org/hibernate/core/3.5/api/org/hibernate/criterion/Distinct.html) via the Projections.distinct() factory method (http://docs.jboss.org/hibernate/core/3.5/api/org/hibernate/criterion/Projections.html)- i.e.:
dc.setProjection(Projections.distinct(Projections.property("id")));
Something like that should do what you need.