Querying Mongo Collection using QueryBuilder in Mongo 3.3.0 - java

Our code with mongo-java-driver 3.0.4 used to be like -
DBCollection dbCollection = mongoClient.getDB(databaseName).getCollection(collectionName);
QueryBuilder queryBuilder = new QueryBuilder();
/** queryBuilder.put() for building the query */
DBCursor dbCursor = dbCollection.find(queryBuilder.get());
while(dbCursor.hasNext()) {
DBObject dbObject = dbCursor.next();
// add entries to a list of TDocument type
}
Converting this to the mongo-java-driver 3.3.0, I ended up with this -
MongoCollection<TDocument> collection = database.getCollection(collectionName, TDocument.class); //where TDocument is custom document class of ours
QueryBuilder queryBuilder = new QueryBuilder();
/** queryBuilder.put() for building the query */
FindIterable<TDocument> tDocumentList = collection.find(queryBuilder.get()); //this is not compiling
for (TDocument element : tDocumentList) {
names.add(element.getName()); //addition to some list of TDocument type
}
But the point is I am still not able to compile the source for the find operation on the MongoDB collection that I have defined.
What needs to be corrected here? I would want to stick to any preferred implementation that helps in upgrading mongo to 3.3.0+.
Edit - My TDocument class (named differently below from the lib name) class is a simple POJO as -
public class TDocType {
private TDocType() {
}
String one;
#NotNull
String name;
String third;
String fourth;
// getter and setter for all the above
}

Cast to Bson.
FindIterable<TDocument> tDocumentList = collection.find((Bson)queryBuilder.get());
Update::
Change to use the filters from Mongo 3.3.0
Bson filter = Filters.eq("field", "value");
FindIterable<TDocument> tDocumentList = collection.find(filter);

You could replace your query builder by a org.bson.Document like this :
Document query = new Document();
query.put(parameterName, parameterValue);
And then
FindIterable<TDocument> tDocumentList = collection.find(query); //this is not compiling

Related

Returning IDs list of entities with specified value without defined entity/POJO

I am trying to write a method that returns me IDs (as a List ) of all records from a collection that have a certain status.
I am looking for a solution, but unfortunately I cannot find anything correct.
I currently have something like this:
List<String> getAllLecturersIdList() {
MongoCollection<Document> collection.mongoTemplate.getCollection("lecturers");
MongoCursor<Document> cursor = collection.find().iterator();
ArrayList<String> listOfIDS = new ArrayList<>();
while (cursor.hasNext()) {
listOfIDS.add(cursor.next().getObjectId("_id").toString());
}
return listOfIDS;
}
This method returns me a list of IDs of all lecturers.
The lecturer entity also has a "status" field with values like ACTIVE, LEAVE, FIRED and so on.
I would like to have only IDs of lecturers who have ACTIVE status to be returned to me.
How to do it to have only entities with ACTIVE status when returning from the collection, and not to clean the repository / services level?
Thanks for help in advance!
Important - I don't want an entity structure to be created in the application.
Therefore, the solution cannot contain a POJO / Entity Class and here is the problem (I cannot use e.g. Criteria, because every example is with defined entity )
You can fallback to the low level MongoOperations#executeQuery method if there is no result type mapping your query results:
List<String> getAllLecturersIdList() {
Query query = new Query();
query.fields().include("_id");
query.addCriteria(Criteria.where("status").is("ACTIVE"));
ArrayList<String> listOfIDS = new ArrayList<>();
mongoTemplate.executeQuery(query, "lecturers", document -> listOfIDS.add(document.getObjectId("_id").toString()));
return listOfIDS;
}
The following should work:
List<String> getAllLecturersIdList() {
MongoCollection<Document> collection.mongoTemplate.getCollection("lecturers");
MongoCursor<Document> cursor = collection.find().iterator();
ArrayList<String> listOfIDS = new ArrayList<>();
while (cursor.hasNext()) {
Document document = cursor.next();
if (document.getString("status") == "ACTIVE") {
listOfIDS.add(document.getObjectId("_id").toString());
}
}
return listOfIDS;
}

How to distinct query in MongoDB with projection and filters?

I have list of attributes in mongo and I am querying some nested field. Here is my code,
public List<Brand> searchBrands(Request request) {
final MongoCollection<Document> collection = mongoDatabase.getCollection("shop");
final Document query = new Document();
final Document projection = new Document();
final List<Brand> brandList = new ArrayList<>();
query.append("_id", request.getId());
query.append("isActive", true);
if (request.Year() != null) {
query.append("attributes.name", "myYear");
query.append("attributes.value", request.getYear());
}
projection.append("brand.code", 1.0);
projection.append("brand.description", 1.0);
projection.append("_id", 0.0);
Block<Document> processBlock = document -> brandList.
add(Brand.builder().code(document.get("brand",Document.class).getString("code"))
.description(document.get("brand",Document.class).getString("description"))
.build());
collection.find(query).projection(projection).forEach(processBlock);
return brandList;}
Above code return results correctly, 72 item with same brand.code. But I want to fetch distinct according to brand.code How can I do that?
I'm not sure which mongodb client library you're using to create queries for mongodb;
I'm sharing the query that you can run in mongodb console to get the results you want. I hope you know how to create this query using your mongodb client library
db.shop.distinct('brand.code', myQuery)
//Replace myQuery with your query e.g. {isActive: true}

Search and filter with Spring Data Elasticsearch

I have a JPA entity called Invoice with some properties and want to search and filter the results, but the filter is not working properly. I tried various combinations but no one worked for me.
This one correctly searches for instances having "foobar" in some of the properties:
// this is the search string...
String search = "foobar*";
QueryBuilder queryStringQuery = QueryBuilders.queryStringQuery(search);
NativeSearchQueryBuilder searchQuery = new NativeSearchQueryBuilder();
searchQuery.withQuery(queryStringQuery);
// build and run against the ElasticsearchRepository
NativeSearchQuery query = searchQuery.build();
Page<T> result = searchRepository.search(query);
This is working and gives me all invoices, but now I only want to have "new invoices", which is given by a property called "state", which then has the value "New".
Currently, last one I tried is this one (according to similar questions on SO):
String search = "foobar*";
QueryBuilder queryStringQuery = QueryBuilders.queryStringQuery(search);
NativeSearchQueryBuilder searchQuery = new NativeSearchQueryBuilder();
searchQuery.withQuery(queryStringQuery);
// add filter
QueryBuilder filters = QueryBuilders.termQuery("state", "New");
searchQuery.withFilter(searchFilters);
// build and run against the ElasticsearchRepository
NativeSearchQuery query = searchQuery.build();
Page<T> result = searchRepository.search(query);
This one gives me an empty result, although there must be some results.
I also tried to create somthing like this, but this is also not working:
String search = "foobar*";
QueryBuilder queryStringQuery = QueryBuilders.queryStringQuery(search);
searchFilters = QueryBuilders.termQuery("state", "New");
BoolQueryBuilder searchQuery = QueryBuilders.boolQuery().should(queryStringQuery).must(searchFilters);
Iterable<T> result = searchRepository.search(searchQuery);
Use something like this
QueryBuilder qb;
QueryBuilder stateFilters = QueryBuilders.boolQuery();
((BoolQueryBuilder) filters).filter(QueryBuilders.matchQuery("state", "New"));
qb = QueryBuilders.boolQuery().should(QueryBuilders.queryStringQuery("foobar*")).filter(stateFilters );
the filter function here helps us with this
here qb will have the proper query which can now be used to search using the elasticsearchRepository.search(qb);
Here is some information from spring docs:
https://docs.spring.io/spring-data/elasticsearch/docs/current/reference/html/#elasticsearch.operations

How to query only the specific fields in MongoDB with Java?

I'm using MongoDB 3.2 and MongoDB Java Driver 3.2. In order to query document I use the following code:
Document query = new Document("fetchStatus", new Document("$lte", fetchStatusParam));
ArrayList<Document> unfetchedEvents = dbC_Events.find(query).into(new ArrayList<Document>());
This query works but the problem is that in this case all fields of the document are retrieved (analog of select * in SQL). In order to optimize query performance, I want to specify fields I really need and fetch only them.
I found couple of examples, such as:
BasicDBObject query = new BasicDBObject();
BasicDBObject fields = new BasicDBObject("Name", 1);
coll.find(query, fields);
but all of them are designed for outdated version of MongoDB Java Driver, e.g. 2.4, while I'm using 3.2.
How can I query only specific fields of document in MongoDB Java Driver 3.2?
There is a .projection() method that is chainable to the query result which allows you to specify fields.
Either expressed as a document, with the familiar and well documented BSON syntax:
ArrayList<Document> unfecthedEvents = collection.find(
new Document("fetchStatus", new Document("$lte", fetchStatusParam))
).projection(
new Document("Name",1)
).into(new ArrayList<Document>());
Or as a fields property builder which really just translates to exactly the same BSON:
ArrayList<Document> unfecthedEvents = collection.find(
new Document("fetchStatus", new Document("$lte", fetchStatusParam))
).projection(
fields(include("Name"))
).into(new ArrayList<Document>());
It worked for me as well:
BasicDBObject whereQuery = new BasicDBObject();
BasicDBObject fields = new BasicDBObject();
// the conditions in where query
whereQuery.put("dzeeClient", dzeeClient);
whereQuery.put("recommendationRunType", planView);
whereQuery.put("recommendedPlans.enrolled",employeeViewed);
// the fields to be returned from the query-only loginId, and remove _id
fields.put("loginId", 1);
fields.put("_id", 0);
FindIterable<Document> cursor = collection.find(whereQuery)
.projection(fields).sort(new BasicDBObject("timeStamp",-1)).limit(1);

How to upsert with mongodb-java-driver

How can I upsert data into mongodb collection with java-driver?
I try (with empty collection):
db.getCollection(collection).update(new BasicDBObject("_id", "12"), dbobject, true, false);
But document was created with _id == ObjectID(...). Not with "12" value.
This code (js) add document with _id = "12" as expected
db.metaclass.update(
{ _id:12},
{
$set: {b:1}
},
{ upsert: true }
)
mongo-java-driver-2.11.2
If you are using mongo-java driver 3, following .updateOne() method with {upsert, true} flag works.
void setLastIndex(MongoClient mongo, Long id, Long lastIndexValue) {
Bson filter = Filters.eq("_id", id);
Bson update = new Document("$set",
new Document()
.append("lastIndex", lastIndexValue)
.append("created", new Date()));
UpdateOptions options = new UpdateOptions().upsert(true);
mongo.getDatabase(EventStreamApp.EVENTS_DB)
.getCollection(EventCursor.name)
.updateOne(filter, update, options);
}
You cannot set _id if dbobject is just a document and does not contain an update operator eg: $set, $setOnInsert.
Just passing a document will replace the whole document meaning it doesn't set an _id a falls back to ObjectId
So your example works if you use an update operator eg:
db.getCollection(collection).update(
new BasicDBObject("_id", "12"),
new BasicDBObject("$set", new BasicDBObject("Hi", "world")), true, false)
You can use the replaceOne method and specify the ReplaceOptions (since 3.7) :
private static final ReplaceOptions REPLACE_OPTIONS
= ReplaceOptions.createReplaceOptions(new UpdateOptions().upsert(true));
db.getCollection(collection).replaceOne(new BasicDBObject("_id", "12"), dbobject, REPLACE_OPTIONS);
For older versions you can directly pass the UpdateOptions to the replaceOne method :
private static final UpdateOptions UPDATE_POLICY = new UpdateOptions().upsert(true);
db.getCollection(collection).replaceOne(new BasicDBObject("_id", "12"), dbobject, UPDATE_POLICY);
As mentioned in the documentation :
replaceOne() replaces the first matching document in the collection
that matches the filter, using the replacement document.
If upsert: true and no documents match the filter, replaceOne()
creates a new document based on the replacement document.
This is to upsert with scala driver which i couldnot find in web
con.updateOne(
equal("vendor_id", vendorId),
inc("views_count", f.views),
UpdateOptions().upsert(true))
to do so import the following
import org.mongodb.scala.model.UpdateOptions

Categories

Resources