is there way to use multiprefix using elasticsearch java api? - java

using QueryBuilders.prefixQuery i'm trying to get the list of book title that starts with "L" or "J" is there any way to achieve that?
I know that QueryBuilders.prefixQuery can accept only string like boolQueryBuilder.must(QueryBuilders.prefixQuery("bookTitle", "L")); is there any othere simple way to achieve that?

you can use the boolean clause should and combine two prefix query one for L and one for J which will provide your expected search results, means books with starts from either L or J.
In java code it will look below:
BoolQueryBuilder boolQueryBuilder = new BoolQueryBuilder();
PrefixQueryBuilder lPrefixQueryBuilder = new PrefixQueryBuilder("title","L");
PrefixQueryBuilder jPrefixQueryBuilder = new PrefixQueryBuilder("title","J");
boolQueryBuilder.should(lPrefixQueryBuilder);
boolQueryBuilder.should(jPrefixQueryBuilder);

Related

Spring Data MongoDb elemMatch criteria matching all search strings

I'm having an issue with custom Spring Data queries with MongoDb and Java. I'm attempting to implement a flexible search functionality against most of the fields of the document.
This document represents a person, and it contains a set of addresses embedded in it; the address has a field that is a set of strings that are the 'street address lines'.
I started with Query By Example, and this works for the single fields. but doesn't work for other types - such as this set of strings. For these, I'm building custom criteria.
The search criteria includes a set of street lines that I would like to match against the document's lines. If every line in the search is found in the document, the criteria should be considered matching.
I've tried using elemMatch, but this doesn't quite work like I want:
addressCriteriaList.add(Criteria.where("streetAddressLines").elemMatch(new Criteria().in(addressSearch.getStreetAddressLines())));
This seems to match if only ONE line in the document matches the search. If I have the following document:
"streetAddressLines": [ "123 Main Street", "Apt 1" ]
and the search looks like this:
"streetAddressLines": [ "123 Main Street", "Apt 2" ]
the elemMatch succeeds, but that's not what i want.
I've also tried looping through each of the search lines, trying an elemMatch to see if each is in the document:
var addressLinesCriteriaList = new Array<Criteria>();
var streetAddressLines = address.getStreetAddressLines();
streetAddressLines.forEach(l -> addressLinesCriteriaList.add(Criteria.where("streetAddressLines").elemMatch(new Criteria().is(l))))
var matchCriteria = new Criteria.andOperator(addressLinesCriteriaList);
This doesn't seem to work. I have done some experimenting, and it may be that this doesn't seem to work: new Criteria().is(l)
I tried this, and this DOES seem to work, but I would think that it's really inefficient to create a collection for each search line:
streetAddressLines.forEach(l ->
{
var list = new ArrayList<String>();
list.add(l);
addressCriteriaList.add(Criteria.where("streetAddressLines").elemMatch(new Criteria().in(l)));
});
So I don't know exactly what's going on - does anyone have any ideas of what I'm doing wrong? Thanks in advance.
You need to use the $all operator or the all method of Criteria class. Something along these lines:
addressCriteriaList.add(Criteria.where("streetAddressLines").all(addressSearch.getStreetAddressLines()));
If addressSearch.getStreetAddressLines returns a list, try this:
addressCriteriaList.add(Criteria.where("streetAddressLines").all(addressSearch.getStreetAddressLines().toArray(new String[0])));

Java QueryDsl for "update myTable where myColumn in ('interesting', 'values')"?

I'm trying to translate this query in QueryDsl:
update myThings set firstColumn = 'newValue' where secondColumn in ('interesting', 'stuff')
I spent hours looking for documentation but the java fu is just not strong enough in this one... :( I can find all kinds of QueryDsl example, but I cant find any for this. I will probably need SimpleExpression.eqAny(CollectionExpression), but I can't figure out how to build such a CollectionExpression around my simple list of strings.
List<String> interestingValues = Arrays.asList("interesting", "stuff");
queryFactory.update(myThings)
.set(myThings.firstColumn, "newValue")
// .where(myThings.secondColumn.in(interestingValues)
// 'in' will probably try to look in table "interestingValues"?
// .where(myThings.secondColumn.eqAny(interestingValues)
// 'eqAny' seems interesting, but doesn't accept a list
.execute();
All I can find is API definitions, but then I get lost in generics any other "new" java concepts which I still have trouble understanding. An example would be very much appreciated.
You have to use new JPAUpdateClause(session, myThings):
JPAUpdateClause<myThings> update = new JPAUpdateClause(session, myThings);
update.set(myThings.firstColumn, "newValue")
.where(myThings.secondColumn.in(interestingValues))
.execute();
If you are using hibernate, use HibernateUpdateClause() instead;

MongoDB Text Index using Java Driver

Using the MongoDB Java API, I have not been able to successfully locate a full example using text search. The code I am using is this:
DBCollection coll;
String searchString = "Test String";
coll.createIndex(new BasicDBObject ("blogcomments", "text"));
DBObject q = start("blogcomments").text(searchString).get();
The name of my collection that I am performing the search on is blogcomments. creatIndex() is the replacement method for the deprecated method ensureIndex(). I have seen examples for how to use the createIndex(), but not how to execute actual searches with the Java API. Is this the correct way to go about doing this?
That's not quite right. Queries that use indexes of type "text" can not specify a field name at query time. Instead, the field names to include in the index are specified at index creation time. See the documentation for examples. Your query will look like this:
DBObject q = QueryBuilder.start().text(searchString).get();

Using regular Expressions with Mongodb

I am using Java Spring to work with Mongodb. I need to find documents which the word 'manager' is existed in description field. I tried following two method
Method 1
Query query = new Query();
query.addCriteria(Criteria.where("discription").regex("/\bmanager\b/"));
Method 2
Query query = new Query();
Pattern p = Pattern.compile("/\bmanager\b/");
query.addCriteria(Criteria.where("discription").regex(p));
But none of these were worked. I tried it with mongodb console like this
db.test.find({discription: {$regex: /\bmanager\b/}})
It worked as I expected. What's wrong with my Java code.
You don't have to add the slashes in the regex expression, as the regex method takes care of it. So
Query query = new Query();
query.addCriteria(Criteria.where("description").regex("\bmanager\b"));
should work.
It looks like you can just pass your regex string straight through without using Pattern.compile(). Have you tried that?

How to query mongodb with “like” using the java api without using Pattern Matching?

Currently I am using java to connect to MONGODB,
I want to write this sql query in mongodb using java driver:
select * from tableA where name like("%ab%")
is their any solution to perform the same task through java,
the query in mongodb is very simple i know, the query is
db.collection.find({name:/ab/})
but how to perform same task in java
Current I am using pattern matching to perform the task and code is
DBObject A = QueryBuilder.start("name").is(Pattern.compile("ab",
Pattern.CASE_INSENSITIVE)).get();
but it makes query very slow I think , does a solution exist that does not use pattern matching?
Can use Regular Expressions. Take a look at the following:
http://www.mongodb.org/display/DOCS/Advanced+Queries#AdvancedQueries-RegularExpressions
Make sure you understand the potential performance impacts!
DBObject A = QueryBuilder.start("name").is(Pattern.compile("ab",
Pattern.CASE_INSENSITIVE)).get();
I think this is one of the possible solution, you need to create index to achieve those.
Why do you fear the regular expressions? Once the expression is compiled they are very fast, and if the expression is "ab" the result is similar to a function that search a substring in a string.
However to do what you need you have 2 possibilities:
The first one, using regular expression, as you mention in your question. And I believe this is the best solution.
The second one, using the $where queries.
With $where queries you can specify expression like these
db.foo.find({"$where" : "this.x + this.y == 10"})
db.foo.find({"$where" : "function() { return this.x + this.y == 10; }"})
and so you can use the JavaScript .indexOf() on string fields.
Code snippet using the $regex clause (as mentioned by mikeycgto)
String searchString = "ab";
DBCollection coll = db.getCollection("yourCollection");
query.put("name",
new BasicDBObject("$regex", String.format(".*((?i)%s).*", searchString)) );
DBCursor cur = coll.find(query);
while (cur.hasNext()) {
DBObject dbObj = cur.next();
// your code to read the DBObject ..
}
As long as you are not opening and closing the connection per method call, the query should be fast.

Categories

Resources