Disclaimer: I am new to MongoDB. I just started to use it few days back. Sorry if my question doesn't make much sense.
Hello,
I am trying to make a Query to MongoDB from Java method, I want to create and make a query only if that parameter is not null. So let us say that my method is
public List<Object> getSomethingFromMongoDB(String searchParameter){
Query query = new Query().addCriteria(Criteria.where("something").is((searchParameter)));
}
Now I only want to search when SearchParameter only when it is notNull. Can I do this in a better way? I tried to check $ne but cannot understand how to apply it in my Java method.
Thanks in advance
I would advise the following:
public List<Document> getSomethingFromMongoDB(List<String> searchParameters){
List<Document> results = new ArrayList<>();
if (searchParameters == null) return results;
Document criteria = new Document();
searchParameters.forEach(parameter -> criteria.append("yourField",parameter));
collection.find(criteria).iterator().forEachRemaining(results::add);
return results;
}
If the parameters list is empty, you will just get all the documents.
If not, the corresponding criteria will be applied.
You could even get rid of the null-checking line, by making sure you pass a new ArrayList() for example, instead of null.
Related
Having a simple SQL Table like:
NOTIFICATION (ID, NAME, NOTIF_DATE, ...)
I am excecuting a SQL query from my back-end app using code like:
this.findBySQL(MY_SQL_QUERY, params...);
The SQL SELECT QUERY is excecuted correctly and returns the rows expected. The problem i am facing is that the returned rows are wrapped to Object[], but after this query, i want to filter the results using Java 8 stream and filter functionality.
I want the results to be mapped to my custom Object Notification, which look like:
Notification { long id, String name, Date notif_date, ... }
I could create my own mapper, getting the result values from the Object i get from the query, example:
Notification not = new Notification();
not.setName(obj[1]);
...
But i think that this approach is not a good implementation beacause it depends on the order of the columns returned, and i have to code for every attribute to be setted.
Is there any way of mapping from this Object[] to my Notification?
Thanks in advance and sorry for the poor code but I have no better approach for this issue.
It’s easiest if your Notification class has a constructor that accepts the fields from the database (or you can add such a constructor):
List<Object[]> rows = this.findBySQL(MY_SQL_QUERY, params);
List<Notification> notifs = rows.stream()
.map(r -> new Notification((Long) r[0], (String) r[1], (Date) r[2]))
.filter(n -> n.getName().startsWith("m"))
.collect(Collectors.toList());
You haven’t told us the exact return type of findBySQL(), so I am guessing a bit. I hope you will be able to tailor the code to your exact situation.
I put in a fairly meaningless filter() in the stream just for the sake of the example. I would find it more convenient to filter after you have created the Notification objects. You can also filter before if you prefer. I didn’t really understand why you didn’t do your filtering in SQL.
If you cannot add a good constructor for the purpose, it’s a bit longer, but really not very much more complicated:
List<Notification> notifs = rows.stream()
.map(r -> {
Notification notif = new Notification();
notif.setId((Long) r[0]);
notif.setName((String) r[1]);
notif.setNotif_date((Date) r[2]);
return notif;
})
.filter(n -> n.getName().startsWith("m"))
.collect(Collectors.toList());
I'm having a problem with MongoDB using Java when I try adding documents with customized _id field. And when I insert new document to that collection, I want to ignore the document if it's _id has already existed.
In Mongo shell, collection.save() can be used in this case but I cannot find the equivalent method to work with MongoDB java driver.
Just to add an example:
I have a collection of documents containing websites' information
with the URLs as _id field (which is unique)
I want to add some more documents. In those new documents, some might be existing in the current collection. So I want to keep adding all the new documents except for the duplicate ones.
This can be achieve by collection.save() in Mongo Shell but using MongoDB Java Driver, I can't find the equivalent method.
Hopefully someone can share the solution. Thanks in advance!
In the MongoDB Java driver, you could try using the BulkWriteOperation object with the initializeOrderedBulkOperation() method of the DBCollection object (the one that contains your collection). This is used as follows:
MongoClient mongo = new MongoClient("localhost", port_number);
DB db = mongo.getDB("db_name");
ArrayList<DBObject> objectList; // Fill this list with your objects to insert
BulkWriteOperation operation = col.initializeOrderedBulkOperation();
for (int i = 0; i < objectList.size(); i++) {
operation.insert(objectList.get(i));
}
BulkWriteResult result = operation.execute();
With this method, your documents will be inserted one at a time with error handling on each insert, so documents that have a duplicated id will throw an error as usual, but the operation will still continue with the rest of the documents. In the end, you can use the getInsertedCount() method of the BulkWriteResult object to know how many documents were really inserted.
This can prove to be a bit ineffective if lots of data is inserted this way, though. This is just sample code (that was found on journaldev.com and edited to fit your situation.). You may need to edit it so it fits your current configuration. It is also untested.
I guess save is doing something like this.
fun save(doc: Document, col: MongoCollection<Document>) {
if (doc.getObjectId("_id") != null) {
doc.put("_id", ObjectId()) // generate a new id
}
col.replaceOne(Document("_id", doc.getObjectId("_id")), doc)
}
Maybe they removed save so you decide how to generate the new id.
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;
I am writing a select query in hql , my task is to activate the bus. First I will get a messege from client as busId#busStatus, so first I look for this perticular busId is active or inactive So I have to write select query but in hibernate query.list() returns list. Here I think list is unnecessary , a single object is enough .
Here is my code ,
String hql="from BusDetailBean where Busid= :busId and bus_status=:busStatus";
Query query = session.createQuery(hql);
query.setParameter("busId", busId);
query.setParameter("busStatus", busStatus);
List<BusDetailBean> busDetails=(List<BusDetailBean>)query.list();
if(busDetails.isEmpty())
{
//my other stuff
}
else
{
//bus ativation stuff
}
My question is the select query returns only one object if list is not empty I have to use for loop in else part. So how can I optimise this code. can anyone help me in this.
You can use query.getSingleResult()
You can use query.setMaxResults(1);
You can get the object at index 0 in the list:
List l = query.list()
if (l.size()>0) {
return l.get(0)
}
I don't think persitence should be mixed with business logic.
What about returning Optional from the persitence layer and whether result is present/absent do something in higher level?
In persistance layer something like:
return query.list()
.stream()
.findFirst()
This, according to docs, will return first result or empty optional if the collection was empty.
And then:
Optional<Bus> optionalBus = repository.find(busId, busStatus);
if (optionalBus.isPresent()) {
something here
} else {
something else
}
by using query.uniqueResult() you don't ensure that if you have many results , then you will get only one of them.
With uniqueResult() you place a guard/contraint at your result set to be aware that this query should always return a unique result.
For this type of problem, the out of the box solution in Hibernate is to use the uniqueResult() method in the Query class:
public Object uniqueResult()
From the Hibernate JavaDocs:
Convenience method to return a single instance that matches the query,
or null if the query returns no results.
Returns: the single result or null
Throws:
NonUniqueResultException - if there is more than one matching result
HibernateException
I am using Playframework 2.1.1 and Java. I am trying to fill a selectbox with data I retrieve from a database using the Play formhelpers
Here is some code if the view:
#helper.form(action = routes.Admin.submitUnit) {
#helper.select(
field = unitForm("metaunit"),
options = options(Metaunit.find)
)
...
}
And the Method to retrieve Metaunits from db:
public static List<Metaunit> find(){
Query query = JPA.em().createQuery("SELECT e FROM Metaunit e");
return (List<Metaunit>)query.getResultList();
}
When I try to compile it, I get the following Error-Message:
Overloaded method value [apply] cannot be applied to (java.util.List[models.Metaunit])
Any help is appreciated! Thanks
Take a look into computer-database-jpa sample ie. options() method in Company model in general it returns Map<String, String>.
As you can see in the editForm view, usage is pretty similar to your.
Note: probably you Metaunit is connected with some M-M relation, in that case most probably you will need to use unitForm("metaunit.id") as a field's value