Can we Convert N1QL to shEL query for Spring use - spring-data-jpa

I am working on spring and couchbase and now want to upload data to couchbase with the help of my spring API but got to know that spring does not support N1QL, So is there any other way to achieve that or a shEL query
insert into bucket1(key,value)
values("Aman--12/04/1995",
{
"English":[{ "midterm": 34, "endterm": 67 }],
"Maths":[{ "midterm": 20, "endterm": 40 }],
"Computer":[{ "midterm": 48, "endterm": 90 }]
})
UPDATE bucketName USE KEYS id
SET arrayname = ARRAY_PUT(IFNULL(Arrayname[]),{"Sports": "89"})

If you can't do something via spEL you can always use pure n1ql for it:
#Override
public void updateAreaName(String areaName, String areaId) {
String queryString = "UPDATE "+getBucketName()+" set areaName = '"+areaName+"' WHERE "+getClassFilter()+" " +
" and areaId = '"+areaId+"' RETURNING meta().id";
N1qlParams params = N1qlParams.build().consistency(ScanConsistency.REQUEST_PLUS).adhoc(true);
ParameterizedN1qlQuery query = N1qlQuery.parameterized(queryString, JsonObject.create(), params);
resourceRepository.getCouchbaseOperations().getCouchbaseBucket().query(query);
}
private String getBucketName() {
return resourceRepository.getCouchbaseOperations().getCouchbaseBucket().bucketManager().info().name();
}
private String getClassFilter(){
return "_class = '" + QResource.class.getName() + "' ";
}

Related

how to query case insensitivity and contains with Spring MongoTemplate

I have JSON documents in MongoDB like these
{
"os" : "Windows 10"
}
{
"os" : "WINDOWS 8"
}
{
"os" : "UBunTu 18.04"
}
how can I query on os with case insensitivity and contains using Spring MongoTemplate so that I can pass ["windows", "ubuntu"] and get all three documents from DB
I tried something like this but did not work.
String osRegEx = String.join(" | ", new String[]{"windows", "ubuntu"});
query.addCriteria(Criteria.where("os").regex(osRegEx, "i"));
It worked in this way...
String osRegEx = String.join("|", new String[]{"windows.*", "ubuntu.*"});
query.addCriteria(Criteria.where("os").regex("("+osRegEx+")", "i"));
I think you are facing this issue because of the string that you have provided for regex. You have Windows 10 etc in mongo with the version number but you are only having the regex string to match the windows/ubuntu part :
String osRegEx = String.join(" | ", new String[]{"windows.*", "ubuntu.*"});
query.addCriteria(Criteria.where("os").regex(osRegEx, "i"));
Here is a solution:
String [] queryStrs = { "windows", "ubuntu" };
String patternStr = Stream.of(queryStrs).collect(Collectors.joining("|", "(", ")"));
Pattern pattern = Pattern.compile(patternStr, Pattern.CASE_INSENSITIVE);
Criteria criteria = new Criteria().regex(pattern);
Query query = Query.query(criteria);
List<Foo> result = mongoTemplate.find(query, Foo.class);

[StitchServiceError: Error: ObjectId in must be a single string of 12 bytes or a string of 24 hex characters]

I am writing Mongodb Stitch, functions.
The weird part is, writing it within Mongodb Stitch function client, it has to do BSON.ObjectId
const games = mongodb.collection("games");
const gameId = "5cb9404ffc6da85909eb561c";
const objectId = BSON.ObjectId(gameId);
const query = { "_id" : objectId };
return games.findOne(query);
But, when I use my app to pass the arg to the function, it will complain
[StitchServiceError: Error: ObjectId in must be a single string of 12 bytes or a string of 24 hex characters]
Which I have to revert it back to
const gameId = "5cb9404ffc6da85909eb561c";
const query = { "_id" : gameId };
return games.findOne(query);
Which this will return null if I test it within MongoDB Stitch function client.
Why MongoDB designs in this way?
For app to work, you only need to pass the id string.
const gameId = "5cb9404ffc6da85909eb561c";
const query = { "_id" : gameId };
return games.findOne(query);
This worked for me:
exports = function(payload, response) {
const mongodb = context.services.get("mongodb-atlas");
const collection = mongodb.db("mydatabase").collection("mycollection");
// const id = "5f2b7706fae92314e01a2c3c";
// let cursor = collection.findOne({_id: BSON.ObjectId(id)});
let cursor = collection.findOne({_id: BSON.ObjectId(payload.query.id)});
cursor.then(function(result){
response.setStatusCode(200);
response.setHeader(
"Content-Type",
"application/json"
);
response.setBody(JSON.stringify(result));
});
};
Then to test:
https://yourwebhookurl?id=5f2b7706fae92314e01a2c3c
Also see: https://intercom.help/mongodb-atlas/en/articles/1566512-how-do-i-work-with-objectid-in-stitch

How to compare two collections and archive documents which are not common

I have two collections for example CollectionA and CollectionB both have common filed which is hostname
Collection A :
{
"hostname": "vm01",
"id": "1",
"status": "online",
}
Collection B
{
"hostname": "vm01",
"id": "string",
"installedversion": "string",
}
{
"hostname": "vm02",
"id": "string",
"installedversion": "string",
}
what i want to achieve is when i receive a post message for collection B
I want to check if the record exists in Collection B based on hostname and update all the values. if not insert the new record ( i have read it can be achieved by using upsert -- still looking how to make it work)
I want to check if the hostname is present in Collection A , if not move the record from collection B to another collection which is collection C ( as archive records).ie in the above hostname=vm02 record from collection B should be moved to collectionC
how can i achieve this using springboot mongodb anyhelp is appreciated.The code which i have to save the Collection B is as follows which i want to update to achieve the above desired result
public RscInstalltionStatusDTO save(RscInstalltionStatusDTO rscInstalltionStatusDTO) {
log.debug("Request to save RscInstalltionStatus : {}", rscInstalltionStatusDTO);
RscInstalltionStatus rscInstalltionStatus = rscInstalltionStatusMapper.toEntity(rscInstalltionStatusDTO);
rscInstalltionStatus = rscInstalltionStatusRepository.save(rscInstalltionStatus);
return rscInstalltionStatusMapper.toDto(rscInstalltionStatus);
}
Update 1 : The below works as i expected but I think there should be a better way to do this.
public RscInstalltionStatusDTO save(RscInstalltionStatusDTO rscInstalltionStatusDTO) {
log.debug("Request to save RscInstalltionStatus : {}", rscInstalltionStatusDTO);
RscInstalltionStatus rscInstalltionStatus = rscInstalltionStatusMapper.toEntity(rscInstalltionStatusDTO);
System.out.print(rscInstalltionStatus.getHostname());
Query query = new Query(Criteria.where("hostname").is(rscInstalltionStatus.getHostname()));
Update update = new Update();
update.set("configdownload",rscInstalltionStatus.getConfigdownload());
update.set("rscpkgdownload",rscInstalltionStatus.getRscpkgdownload());
update.set("configextraction",rscInstalltionStatus.getConfigextraction());
update.set("rscpkgextraction",rscInstalltionStatus.getRscpkgextraction());
update.set("rscstartup",rscInstalltionStatus.getRscstartup());
update.set("installedversion",rscInstalltionStatus.getInstalledversion());
mongoTemplate.upsert(query, update,RscInstalltionStatus.class);
rscInstalltionStatus = rscInstalltionStatusRepository.findByHostname(rscInstalltionStatus.getHostname());
return rscInstalltionStatusMapper.toDto(rscInstalltionStatus);
}
Update2 : with the below code i am able to get move the records to another collection
String query = "{$lookup:{ from: \"vmdetails\",let: {rschostname: \"$hostname\"},pipeline:[{$match:{$expr:{$ne :[\"$hostname\",\"$$rschostname\"]}}}],as: \"rscInstall\"}},{$unwind:\"$rscInstall\"},{$project:{\"_id\":0,\"rscInstall\":0}}";
AggregationOperation rscInstalltionStatusTypedAggregation = new CustomProjectAggregationOperation(query);
LookupOperation lookupOperation = LookupOperation.newLookup().from("vmdetails").localField("hostname").foreignField("hostname").as("rscInstall");
UnwindOperation unwindOperation = Aggregation.unwind("$rscInstall");
ProjectionOperation projectionOperation = Aggregation.project("_id","rscInstall").andExclude("_id","rscInstall");
OutOperation outOperation = Aggregation.out("RscInstallArchive");
Aggregation aggregation = Aggregation.newAggregation(rscInstalltionStatusTypedAggregation,unwindOperation,projectionOperation,outOperation);
List<BasicDBObject> results = mongoTemplate.aggregate(aggregation,"rsc_installtion_status",BasicDBObject.class).getMappedResults();
this issue which i have here is it returns multiple records
Found the solution , there may be other best solutions but for me this one worked
create a class customeAggregationGeneration (found in SO answers and extended to match my needs)
public class CustomProjectAggregationOperation implements AggregationOperation {
private String jsonOperation;
public CustomProjectAggregationOperation(String jsonOperation) {
this.jsonOperation = jsonOperation;
}
#Override
public Document toDocument(AggregationOperationContext aggregationOperationContext) {
return aggregationOperationContext.getMappedObject(Document.parse(jsonOperation));
}
}
String lookupquery = "{$lookup :{from:\"vmdetails\",localField:\"hostname\",foreignField:\"hostname\"as:\"rscinstall\"}}";
String matchquery = "{ $match: { \"rscinstall\": { $eq: [] } }}";
String projectquery = "{$project:{\"rscinstall\":0}}";
AggregationOperation lookupOpertaion = new CustomProjectAggregationOperation(lookupquery);
AggregationOperation matchOperation = new CustomProjectAggregationOperation(matchquery);
AggregationOperation projectOperation = new CustomProjectAggregationOperation(projectquery);
Aggregation aggregation = Aggregation.newAggregation(lookupOpertaion, matchOperation, projectOperation);
ArrayList<Document> results1 = (ArrayList<Document>) mongoTemplate.aggregate(aggregation, "rsc_installtion_status", Document.class).getRawResults().get("result");
// System.out.println(results1);
for (Document doc : results1) {
// System.out.print(doc.get("_id").toString());
mongoTemplate.insert(doc, "RscInstallArchive");
delete(doc.get("_id").toString());

Access item in ListField/EmbeddedDocumentListField by using __raw__ in MongoEngine [duplicate]

I use mongoengine with Django and python.
This is my code:
class Chambre(EmbeddedDocument):
max_personne = IntField(default=0)
prix = IntField(default=0)
class Hotel(Document):
code = IntField(default=0)
nom = StringField(max_length=200)
chambre = ListField(EmbeddedDocumentField(Chambre))
resume = StringField(max_length=200)
1 - I want a query to filter all Hotel that have at least a Chambre with prix >= a (a floeat number)
2 - also have that Chambre
Any idea?
You can use the embedded notation as well as the Query Operator for "greater than or equal "
Hotel.objects(chambre__prix__gte=a)
Or if you need to cast as an integer:
Hotel.objects(chambre__prix__gte=int(math.floor(a)))
If you want to only project the "matched" element, use a raw query directly on the driver instead:
Hotel._get_collection().find(
{ 'chambre.prix': { '$gte': int(math.floor(a)) } },
{ 'chambre.$': 1 }
)

Put without fetch in Backbone

i want to update a record:
www.mywebsite.com/REST/mytable/16
But; for mytable, i have to give two mandatory parameters:
www.mywebsite.com/REST/mytable?param1=this&param2=that
And if i want to take the model from this collection using the following, the record can't be found:
www.mywebsite.com/REST/mytable?param1=this&param2=that/16
This is realized by the following code:
var Model = Backbone.Model.extend({
idAttribute : "ID"
});
var Col = Backbone.Collection.extend({
model : Model,
url : $scope.base + $scope.selected.table.entity.Name + "?param1=1&param2=2"
});
connector.fetch().then(function () {
var record = connector.get(toBeChangedRecordId);
record.set(props); //attributes as json
.save({
success : $scope.putCallback,
error : $scope.putCallback
});
}
It doesn't work because in the url above, no record is found. Instead of this, i need another way, so i can just give my ID to change the record (thus www.mywebsite.com/REST/mytable/16 + JSON object. How is that possible?
When you are doing a dynamic URL like this you can wrap the url method in a function like so
Backbone.Model.extend({
idAttribute : "ID",
url: function() {
var idStr = ''
if (this.isNew()) {
idStr = '/' + this.get('id')
}
return 'http://www.mywebsite.com/REST/mytable' + idStr + '?param1=' + this.get('param1') + '&param2=' + this.get('param2');
}
});
Also, you declared your url was semantically declared wrong. You have the query string in the wrong place.