Spring Mongo criteria on list of list - java

Hi I am using spring data mongo, I need to fetch data based on multiple where condition. The problem I have when I want to apply a where clause to a list in a list.
For example
{
"_id" : ObjectId("5982bf9339f3c92b84be4737"),
"_class" : "com.paladion.payment.model.GroupQuestionMapping",
"saqID" : "SAQ A",
"saqVersion" : "3",
"questionTab" : {
"Secure Network" : [
{
"number" : "2.1 (a)",
"question" : "Are vendor-supplied"
"description" : "<ul><li>Review"
},
{
"number" : "2.1 (b)",
"question" : "Are unnecessary"
"description" : "<ul><li>Review policies
}
],
"Access Control" : [
{
"number" : "2.1 (a)",
"question" : "Are vendor-supplied"
"description" : "<ul><li>Review"
},
{
"number" : "2.1 (b)",
"question" : "Are unnecessary"
"description" : "<ul><li>Review policies
}
]
}
}
Over here I need to fetch data where saqId is SAQ A and saq Version is 3 and questionTab is secure network.
I have problem in applying criteria on questionTab.
my code:
Query query = new Query();
query.addCriteria(Criteria.where("saqtype").is(saqType));
query.addCriteria(Criteria.where("saqversion").is(saqVersion));
query.addCriteria(/* criteria on questionTab */);

query.addCriteria(Criteria.where("questionTab.Secure Network").exists(true));
Thing to note is that it will bring you the full document based on criteria, so you would have to filter out other type of questionTab from document.
Other way is aggregation but then I think processing on application layer might be preferable.

Related

Spring MongoTemplate: Possible to Get and Count all distinct values from Key value Object in each document

I have a large-ish dataset (+100,000) documents. In each document, there is a key value object called ProjectCategories for which I would like to be able to get distinct count on each of the values across the entire collection.
For example my document looks like this:
"_id" : ObjectId("60e5ae42fcc92f14c3a41208"),
"userId" : "xxxx",
"projectCreator" : {
"userId" : "xxx|xxxx"
},
"hashTags" : [
"Spring",
"Java"
],
"projectCategories" : {
"60d76ef0597444095b8ab4b2" : "Backend",
"60d76ef0597444095b8ab232" : "Infrastructure"
},
"createdDate" : ISODate("2021-07-07T13:38:10.655Z"),
"updatedAt" : ISODate("2021-07-08T11:48:36.200Z"),
"_class" : "xxxx.model.project.Project"
}
I would like to get back all the unique values and their counts. Something like this:
Backend : 1002
FrontEnd : 1232
Infrastructure: 902
Is this possible to do using Java and mongoTemplate
Thanks for reading

id is being replaced by _id, of the inner object, when updating data of MongoDB using Java Driver

I'm trying to update an object of MongoDB. I'm using Java Driver (Sync).
After a 'create' operation, the data is persisted as follows:
{
"_id" : ObjectId("5f2b7deb62798d1045a47313"),
"name" : "John",
"other_info" : {
"images" : {
"images" : [
{
"id" : "1",
"imgType" : "IDBACKIMAGE"
},
{
"id" : "2",
"imgType" : "SIGCARDIMAGE"
}
]
},
},
"status" : "PENDING"
}
Now, I want to modify the 'id' parameter of the images array. So I update the data using getCollection().updateOne(filterCondition, combine(updateData)), but it is persisted as below:
{
"_id" : ObjectId("5f2b7deb62798d1045a47313"),
"name" : "John",
"other_info" : {
"images" : {
"images" : [
{
"_id" : "3",
"imgType" : "IDBACKIMAGE"
},
{
"_id" : "4",
"imgType" : "SIGCARDIMAGE"
}
]
},
},
"status" : "PENDING"
}
As you can see in the updated data, the 'id' property of the images array is now '_id' after update operation. I had provided the JSON with 'id' field but somehow the Mongo Client considered 'id' as '_id' and persisted '_id'. This happens when replaceOne() is used too. This doesn't happen with the create operation as you can see above. Is this an expected behavior when update operation is done? Why is MongoDB treating 'id' and '_id' as same?

What is wrong with this Cypher query?

I am trying to send the following to Neo4j using the REST interface, specifically the method given in the 2.2.9 manual tutorial on using REST from Java, sendTransactional Cypher query. However, as you can see below, I keep on getting an error that doesn't seem to have much to do with the query itself.
Any tips on how I can debug this?
CREATE (p:player { props }), "parameters" {
"props" : {
"screen_name" : "testone",
"email" : "test.one#gmail.com",
"rank" : "-12",
"password" : "testonepass",
"details" : "test one details",
"latitude" : "0.0",
"longitude" : "0.0",
"available" : "true",
"publish" : "true" }}
{"results":[],"errors":[{"code":"Neo.ClientError.Request.InvalidFormat","message":"Unable to deserialize request: Unexpected character ('p' (code 112)): was expecting comma to separate OBJECT entries\n at [Source: HttpInputOverHTTP#10401de; line: 1, column: 66]"}]}
Form the snippet you posted, it looks like the payload to the transactional endpoint is incomplete. You could try this statement in the browser. I just copied your statement and formatted it so it could be posted to the browser. Then you can at least see it work. Clearly the data is being posted and it seems it is just comes down to formatting.
:POST /db/data/transaction/commit {
"statements": [
{
"statement": "CREATE (p:player { props })",
"parameters":
{
"props" : {
"screen_name" : "testone",
"email" : "test.one#gmail.com",
"rank" : "-12",
"password" : "testonepass",
"details" : "test one details",
"latitude" : "0.0",
"longitude" : "0.0",
"available" : "true",
"publish" : "true" }
}
}
]
}

How to find user on the basis of its ID in mongodb using java criteria query?

Friends I have come across a problem of finding the user on the basis of user id . My user id is in long form and I am using this code to fetch user
Query query = new Query(Criteria.where("user.$id").is(userId));
User user = mongoTemplate.findOne(query, User.class);
And I am using counter to set id while saving user so in DB my collection is in this form
db.users.find().pretty()
{
"_id" : NumberLong(1),
"_class" : "com.domain.user.User",
"age" : 20,
"username" : "abc#gmail.com",
"roles" : [
"ROLE_USER"
],
"firstName" : "abc",
"lastName" : "xyz",
"email" : "abc#gmail.com",
"gender" : "male",
"isAccountLocked" : false,
"prefAgeFrom" : 0,
"prefAgeTo" : 0,
"aboutMe" : "I like to meet new people",
"notificationNewMatch" : true,
"notificationMessage" : true,
"updatedDate" : ISODate("2015-06-08T07:30:45.878Z")
}
So on the basis of id which is stored in NumberLong(1) form I want to get user of id = 1.
In present scenerio, I am getting user null on the basis of id mentioned above.
My main requirement is that I want to fetch token on the basis of user. My token stored in DB in this form
db.authenticationToken.find().pretty()
{
"_id" : NumberLong(4),
"_class" : "com.domain.user.AuthenticationToken",
"token" : "6db92ee4-2c23-42ee-985e-08af8e3d4f58",
"updatedDate" : ISODate("2015-06-10T04:47:34.434Z"),
"user" : DBRef("users", NumberLong(1))
}
Can anyone help me!
Doing some research over my issue i finally got the solution , we can find the token on the basis of user id like this
Query query = new Query(Criteria.where("user").is(userId))
mongoTemplate.findOne(query,AuthenticationToken.class);

How to construct query to update nested array document in mongo?

I am having following document in mongo,
{
"_id" : ObjectId("506e9e54a4e8f51423679428"),
"description" : "ffffffffffffffff",
"menus" : [
{
"_id" : ObjectId("506e9e5aa4e8f51423679429"),
"description" : "ffffffffffffffffffff",
"items" : [
{
"name" : "xcvxc",
"description" : "vxvxcvxc",
"text" : "vxcvxcvx",
"menuKey" : "0",
"onSelect" : "1",
"_id" : ObjectId("506e9f07a4e8f5142367942f")
} ,
{
"name" : "abcd",
"description" : "qqq",
"text" : "qqq",
"menuKey" : "0",
"onSelect" : "3",
"_id" : ObjectId("507e9f07a4e8f5142367942f")
}
]
},
{
"_id" : ObjectId("506e9e5aa4e8f51423679429"),
"description" : "rrrrr",
"items" : [ {
"name" : "xcc",
"description" : "vx",
"text" : "vxc",
"menuKey" : "0",
"onSelect" : "2",
"_id" : ObjectId("506e9f07a4e8f5142367942f")
} ]
}
]
}
Now , i want to update the following document :
{
"name" : "abcd",
"description" : "qqq",
"text" : "qqq",
"menuKey" : "0",
"onSelect" : "3",
"_id" : ObjectId("507e9f07a4e8f5142367942f")
}
I am having main documnet id: "_id" : ObjectId("506e9e54a4e8f51423679428") and menus id
"_id" : ObjectId("506e9e54a4e8f51423679428") as well as items id "_id" : ObjectId("507e9f07a4e8f5142367942f") which is to be updated.
I have tried using the following query:
db.collection.update({ "_id" : { "$oid" : "506e9e54a4e8f51423679428"} , "menus._id" : { "$oid" : "506e9e5aa4e8f51423679429"}},{ "$set" : { "menus.$.items" : { "_id" : { "$oid" : "506e9f07a4e8f5142367942f"}} , "menus.$.items.$.name" : "xcvxc66666", ...}},false,false);
but its not working...
The positional operator does not work on the number of levels you are trying to get it to work on ( https://jira.mongodb.org/browse/SERVER-831?focusedCommentId=22438&page=com.atlassian.jira.plugin.system.issuetabpanels%3Acomment-tabpanel ) with menus.$.items.$.name and even if it did MongoDB query parser would have no idea what the other $ is from the find of the update.
You will need to pull out the items from the schema, update that seprately and then update the root document.
One good way of judging when queries should be done separately is to think that each menu sounds like a separate entity (or table in a relational database) as such you should probably work on updating those entites (or tables in a relational model) separately to the parent entity (table).
So first you would get out the main root document. Scroll across it's menus in client side and then $set that particular menu to the entire item you build on client side.
Edit
The way I imagine this work client side is (in pseudo code since my Java is a little rusty) by first getting that document in an active record fashion:
doc = db.col.find({ "_id" : { "$oid" : "506e9e54a4e8f51423679428"} ,
"menus._id" : { "$oid" : "506e9e5aa4e8f51423679429"}});
Then you would iterate through the document assigning your values:
foreach(doc.menus as menu_key => menu){
foreach(menu['items'] as key => item){
if(item._id == { "$oid" : "506e9f07a4e8f5142367942f"}){
doc.menus[menu_key][key][name] = "xcvxc66666"
}
}
}
And then simple save the doc after all changes are commited:
db.col.save(doc);
This is of course just one way of doing it and this way uses the activen record paradigm which I personally like. In this idea you would combine the find with everything else you need to modify on the document, building it up client side and then sending it all down as one single query to your DB.

Categories