Query MongoDB with dynamic selector in Camel - mongodb

I found a solution here: How do I create a dynamic equals query using Apache Camel and MongoDB?
But this looks like a lot of work. Doesn't Camel have a simpler way to pass values to a MongoDB query? I wish we could just pass the actual find({}) language that Mongo uses.
Here is what I have working, with some logging showing what it's doing:
.setHeader(MongoDbConstants.CRITERIA, new Expression() {
#Override
public <T> T evaluate(Exchange exchange, Class<T> type) {
Long drRequestId = exchange.getIn().getHeader("orderid", Long.class);
Bson equalsClause = Filters.eq("id", drRequestId);
return exchange.getContext().getTypeConverter().convertTo(type, equalsClause);
};
})
.log(MongoDbConstants.CRITERIA)
.log("${headers.CamelMongoDbCriteria}")
.to("mongodb:mongo?database={{spring.data.mongodb.database}}&collection=ftx_orders&operation=findOneByQuery")

did you try with ${body.id}?
Also, you can also send it in header, setting using
exchange.getIn().setHeader("id","value");
and then using the same way you mentioned above.
.setHeader(MongoDbConstants.CRITERIA, constant(Filters.eq("name", simple("${header.id}"))))

Related

PanacheMongo find with wildcard

I am trying to do a simple find in Panache but I'm stuck with the wildcard operator.
I have:
Model.find("payload.tags.name = ?1", "tag-to")
.stream()
.map(m -> (Model) m)
.collect(Collectors.toList());
and my document looks something like this:
{
...
payload:Object{
swagger:"2.0"
info:Object
host:"petstore.swagger.io"
basePath:"/v2"
tags:Array[
0:Object [
name:"tag-to-find"
description:"a tag i want to find"
]
]
}
}
When I try to find "tag-to-find" it works, but I don't know how to get the wildcards going. In mongoshell i just use db.Model.find({"payload.tags.name": /ag-to-/}) and it works.
What you are using in Mongo shell is a JavaScript regex.
You should also be able to use it with MongoDB with Panache.
You should normaly use the regex with the $regex operator, not sure how Mongo shell handle it but the following should work:
Model.list("payload.tags.name like ?1", "/tag-to/")
I use .list() instead of find() as it directly return the list of documents.
The query used here is what we called PanacheQL query that will maps to a MongoDB native query, you can also use a native query directly (with named or indexed parameters).
Simplified query is explained here: https://quarkus.io/guides/mongodb-panache#simplified-queries

'not equals' condition when using Spring CrudRepository

How should I build my findBy method name so I can implement a where clause -
statusCode != 'Denied'
Is this be an option?
findByStatusCodeNotIn(List<String> statusCode);
What if I want to just pass a String instead of a list?
Thank You
Have you taken a look at the documentation about this in the Spring Data JPA docs?
#findByStatusCodeNot(String statusCode);
It's akin the example in the docs like:
#findByLastnameNot
According to the Spring Data JPA Documentation on https://docs.spring.io/spring-data/jpa/docs/current/reference/html/#reference
you can achieve this by using the "Not" keyword. forinstance your method would be
findByStatusCodeNot(String statusCode);
This means to achieve "statusCode != 'Denied'", you would call the method as
findByStatusCodeNot('Denied');
#Dovmo is right, but also keep in mind that if you are operating on String data, you may have to take case into account, i.e. findByStatusCodeNot(String statusCode) will find only records that are not 'Denied' as is, but not for instance 'DeniEd'. For case-insensitive searches, you can append IgnoreCase - findByStatusCodeNotIgnoreCase(String statusCode)
In general, please follow the link that #Dovmo gave.
According to the spring JPA repository docs we can use the <> symbol in place of !=
so the query would be
statusCode <> 'Denied'
this would be helpful if you want to write a #Query instead of the inbuild repository methods.

How to use object filter with softlayer rest api?

I read this article and have some problems trying to follow the examples. The following is one of the examples given in that article. The first parameter in the object filter is virtualGuests. This object filter can be used in api https://api.softlayer.com/rest/v3/SoftLayer_Account/VirtualGuests.
object_filter = {
'virtualGuests': {
'datacenter': {
'name': {'operation': 'dal05'}
}
}
}
I want to use the object filter in other api methods, like SoftLayer_Account/getBlockDeviceTemplateGroups for example. My question is how to get/set the first parameter like virtualGuests? I tried several times but failed.
Try to follow these recomendations: Getting first parameter through Service Datatype or How to define the first parameter as simple way?
Getting first parameter through Service Datatype
You are trying to get
SoftLayer_Account::getBlockDeviceTemplateGroups
As you see, you are using SoftLayer_Account service, you need to open its datatype from this service:
You can go here:
http://sldn.softlayer.com/reference/services/SoftLayer_Account and
click on "datatypes" label/option
Or go directly here:
SoftLayer_Account
So, you need to start here, the method that you are using is getBlockDeviceTemplateGroups, if you want to get this information in the datatypes, you should skip the word "get" and looking for "BlockDeviceTemplateGroups" property, so you will have the correct parameter that you need to set at first.
How to define the first parameter as simple way?
If you notice, the only changes were: skip "get" word from the method, in this case is "getBlockDeviceTemplateGroups", so it will be:
"BlockDeviceTemplateGroups"
The next step should be set the first char in lowercase like:
"blockDeviceTemplateGroups"
So, it should be the filter:
object_filter = {
'blockDeviceTemplateGroups': {
'datacenter': {
'name': {'operation': 'dal05'}
}
}
}
References:
Object Filters
Going Further with the SoftLayer API Python Client - Part
1

Meteor/MongoDB limiting the result

I am trying to find all documents and publish at most 5 from the results.
Following this section of the MongoDB doc, I am trying to do this:
Meteor.publish('teams', function () {
return Teams.find().limit(5);
});
Yet, in the server console, I get an exception:
Exception from sub teams id Pm6jKL8Sv3FSDSTfM TypeError: Object [object Object] has no method 'limit'
The following works fine:
Meteor.publish('teams', function () {
return Teams.find({}, {limit:5});
});
Why does the second way work, rather than the first? And where can I find documentation for it?
Meteor's collection API is somewhat different from that of the mongo API. find takes up to two parameters: a selector object, and an options object. options allows you to specify such things as sort, skip, limit and fields, in addition to the meteor-specific reactive and transform.

Play with Meteor MongoID in Monk

I'm building an API using Express and Monk that connects to a database where wrote are mainly handled by a Meteor application.
I know that Meteor uses its own algorithm to generate IDs. So when I do something like that:
id = "aczXLTjzjjn3PchX6" // this is an ID generated by Meteor (not a valid MongoID)
Users.findOne({ _id: id }, function(err, doc) {
console.log(doc);
});
Monk outputs:
Argument passed in must be a single String of 12 bytes or a string of 24 hex characters.
This way, it seems very tricky to me to design a solid and reliable REST API. Thus, I have two questions:
How can I handle the difference in my queries between ids generated by Meteor and valid MongoID()? Is there a simple way to get JSON results from a Meteor database?
Will it be a problem to insert documents from the API which this time will have a valid MongoId()? I will end up with both type of ids in my database, seems very bad to me. :/
As I said in here, in a similar issue you can just override the id converter part of monk:
var idConverter = Users.id; // Keep a reference in case...
Users.id = function (str) { return str; };
But don't expect monk to convert Ids automatically anymore.
How can I handle the difference in my queries between ids generated by Meteor and valid MongoID()? Is there a simple way to get JSON results from a Meteor database?
Nothing much you need to do. When it is a valid ObjectId(mongo db ids) and you got a string just convert it to Object id:
id = ObjectId(id);
User.find(id, ...)
Here's the implementation for monk id method(this.col.id is reference to mongodb native ObjectId):
Collection.prototype.id =
Collection.prototype.oid = function (str) {
if (null == str) return this.col.id();
return 'string' == typeof str ? this.col.id(str) : str;
};
Will it be a problem to insert documents from the API which this time will have a valid MongoId()? I will end up with both type of ids in my database, seems very bad to me. :/
It is bad. Though it won't cause much trouble(in my experience in nodejs) if you be careful. But not all the times you are careful(programmer errors happen a lot), but it's manageable. In static languages(like Java) this is a big NO, because a field can only one type(either string or ObjectId).
My suggestion is that don't use mongodb ObjectId at all and just use strings as ids. On inserts just give it string _id, so the driver won't give it ObjectId. Though you can stop the driver from doing so by overriding pkFactory, but it doesn't seem to be easy with monk.
One more thing is that monk is not actively maintained and it's just a thin layer on top of mongodb. In my experience if you have multiple collections and large/complex code base mongoose will be much better to use.
Just to keep this question updated.
As stated in the docs, Monk is automatically casting the strings into OjbectID.
In order to disable this behaviour without using hacky solutions you'll have to disable that feature. In order to do that you just need to set castIds to false when getting the db.
So:
const Users = db.get('users', { castIds: false });
Now this will work:
Users.findOne({ _id: "aczXLTjzjjn3PchX6" }, function(err, doc) {
console.log(doc);
});