I have following db collection of users.
[{
name : "abc",
obj:{ id : 123 , arr[{fid:"a123",field:"0"},{fid:"b123",field:"0"}]}
},
{
name : "pqr",
obj:{ id : 456 , arr[{fid:"a456",field:"0"},{fid:"b456",field:"0"}]}
}]
I want to update field value of fid : b456 to 1 in mongodb.
How to write query for same
Use $
db.users.update({obj.arr.fid:"b456"},{$set: {"obj.arr.$.field":"1"}})
You can as the below:
db.users.update({"obj.arr.fid": b456 }, {$set: { "obj.arr.$.fid": 1 }})
The positional $ operator acts as a placeholder for the first element
that matches the query document.
Have you tried something?
Maybe this can help you:
db.users.update({name:"pqr"},{$set: {"obj.arr[1].fid":"1"}})
For more info take a look here $set
Related
I have the following CSV:
matchId, score, players.Name, players.Goals
2730319610399, 5-0, John, 3
When I use mongoimport on Studio 3T it is imported in the form I need because of the dot notation:
{
"matchId" : "2730319610399",
"score" : "5-0",
"players" : {
"Name" : "John",
"Goals" : "3"
}
}
My issue is that the csv actually has one more player that I want to add in this import. The array of "players" has two entries.
This is the actual CSV format:
matchId, score, players.Name, players.Goals, players.Name, players.Goals
2730319610399, 5-0, John, 3, Kyle, 2
But this does not work and I get an error of:
Every row will be parsed as one column.
The header contains a duplicate name "players.Name" in columns: [3, 5]
Is it possible to format the CSV so that I can add multiple values into the "players" array? I was thinking of naming it something like players[0].Name and players[1].Name
But that doesn't work because it creates two arrays: players[0] and players[1]
This is what I need the database structure to look like:
{
"matchId" : "2730319610399",
"score" : "5-0",
"players" : {
"Name" : "John",
"Goals" : "3"
},
{
"Name" : "Kyle",
"Goals" : "2"
}
}
Try with this:
matchId, score, players.Name, players.Goals
2730319610399, 5-0, John.Kyle, 3.2
then, use:
db.collection.find().snapshot().forEach(function (test) {
test.players.Name = test.players.Name.split('.');
db.whatevercollection.save(test);
});
db.collection.find().snapshot().forEach(function (test) {
test.players.Goals = test.players.Goals.split('.');
db.whatevercollection.save(test);
});
ok, so the best option would be to import a json file instead of a csv.
For example:
{ "matchId":"2730319610399","score":"5-0","players":[{"Name":"John","Goals":"3"},{"Name":"Kyle","Goals":"2"}]}
{ "matchId":"2830319610399","score":"1-0","players":[{"Name":"Mauri","Goals":"1"}]}
then use mongoimport as follows:
mongoimport --db=TestDB --collection=TestCol --type=json example_file.json
you should see something like this on Robo3T:
I have this collection :
{
username : "user1",
arr : [
{
name : "test1",
times : 0
},
{
name : "test2",
times : 5
}
]
}
I have an array with some object. This objects have a name and the value times. Now I want to add new objects, if my array doesn't contain them. Example:
I have this two objects with the name "test1" and "test2" already in the collection. I want now to insert the objects "test2", "test3" and "test4". It should only add the object "test3" and "test4" to the array and not "test2" again. The value times doesn't do anything in this case, they should just have the value 0 when it gets insert.
Is there a way to do this with one query?
If you can insert test1, test2,... one by one, then you can do something like this.
db.collection.update(
{username : "user1", 'arr.name': {$ne: 'test2'}},
{$push: {
arr: {'name': 'test2', 'times': 0}
}
})
The $ne condition will prevent the update if the name is already present in arr.
You can now use the addToSet operator that is built just for that: adds a value to an array if it does not exist.
Documentation: https://docs.mongodb.com/manual/reference/operator/update/addToSet/
I have collection "users" where username , password,questions are stored . "questions" is an array of documents . I would like to get all users with some questions i.e username , password and an array of questions (some part) How can i do that from console or java ?
Here i want to get username , password and first document of questions which is {question:"dawdaw",answered:0}
You can use slice like this
db.users.find({},{"questions":{$slice:1}})
Hope it will help
Use $elemMatch projection to get the desired result. The following find() operation queries for all documents where the $elemMatch projection returns only the first matching element of the questions array where the question field has a value of "dawdaw" and answered has 0 value:
db.users.find({},
{
"username": 1, "password": 1,
"questions": {
"$elemMatch": {
"question" : "dawdaw",
"answered" : 0
}
}
}
);
From the sample given, the operation returns the following document:
/* 0 */
{
"_id" : ObjectId("561a84ffaa233b38d803509a"),
"username" : "asd#mail.ru",
"password" : "asd",
"questions" : [
{
"question" : "dawdaw",
"answered" : 0
}
]
}
I have a Person collection that is made up of the following structure
{
"_id" : ObjectId("54ddd6795218e7964fa9086c"),
"_class" : "uk.gov.gsi.hmpo.belt.domain.person.Person",
"imagesMatch" : true,
"matchResult" : {
"_id" : null,
"score" : 1234,
"matchStatus" : "matched",
"confirmedMatchStatus" : "notChecked"
},
"earlierImage" : DBRef("image", ObjectId("54ddd6795218e7964fa9086b")),
"laterImage" : DBRef("image", ObjectId("54ddd67a5218e7964fa908a9")),
"tag" : DBRef("tag", ObjectId("54ddd6795218e7964fa90842"))
}
Notice that the "tag" is a DBRef.
I've got a Spring Data finder that looks like the following:
Page<Person> findByMatchResultNotNullAndTagId(#Param("tagId") String tagId, Pageable page);
When this code is executed the find query looks like the following:
{ matchResult: { $ne: null }, tag: { $ref: "tag", $id: ObjectId('54ddd6795218e7964fa90842') } } sort: {} projection: {} skip: 0 limit: 1
Which is fine, I get a collection of 1 person back (limit=1). However the page details are not correct. I have 31 persons in the collection so I should have 31 pages. What I get is the following:
"page" : {
"size" : 1,
"totalElements" : 0,
"totalPages" : 0,
"number" : 0
}
The count query looks like the following:
{ count: "person", query: { matchResult: { $ne: null }, tag.id: "54ddd6795218e7964fa90842" } }
That tag.id doesn't look correct to me compared with the equivalent find query above.
I've found that if I add a new method to org.springframework.data.mongodb.core.MongoOperations:
public interface MongoOperations {
public long count(Query query, Class<?> entityClass, String collectionName);
}
And then re-jig AbstractMongoQuery.execute(Query query) to use that method instead of the similar method without the entityClass parameter then I get the correct paging results.
Question: Am I doing something wrong or is this a bug in Spring Data Mongo?
Edit
Taking inspiration from Christoph I've added the following test code on Git https://github.com/tedp/Spring-Data-Test
The information contained in the Page returned depends on the query executed. Assuming a total number of 31 elements in you collection, only a few of them, or even just one might match the given criteria by referencing the tag with id: 54ddd6795218e7964fa90842. Therefore you only get the total elements that match the query, and not the total elements within your collection.
This bug was actually fixed DATAMONGO-1120 as pointed out by Christoph. I needed to override the spring data version to use 1.6.2.RELEASE until the next iteration of Spring Boot where presumably Spring Data will be up lifted to at least 1.6.2.RELEASE.
I have an collection doc like .
{'_id':1,
'name':'Root',
'taskId':1,
'parentId':"",
'path':[1],
'tasks':[ {"taskId":3,parentId:1,name:'A',status:'Created'},
{"taskId":4,parentId:1,name:'D',status:'Created'},
{"taskId":5,parentId:4,name:'B',status:'Created'},
{'type':'project' , 'proRef':2},
{"taskId":6,parentId:3,name:'E',status:'Started'},
{"taskId":7,parentId:6,name:'C',status:'Stopped'}]
}
Now I want to update multiple array element field ‘status’ to ‘Deleted’ which is inside JSON .Let us assume for taskId 3,4 I need to update status to Deleted . I have tried this query with $in with query($) but it is updating very first element is $in array only. In below query only taskId with 3 is getting updated not 4.
db.projectPlan.update({"_id": 1,'tasks.taskId': {$in :[3,4]}} , {$set: {'tasks.$.status': 'Deleted'}}, {upsert: false, multi: true});
How to update multiple elements in single query.Thanks in advance !!
I'm afraid it's not possible, it's a limitation of MongoDB. From the documentation (http://docs.mongodb.org/manual/reference/operator/update-array/):
$ Acts as a placeholder to update the first element that matches the
query condition in an update.
See this ticket for more details: https://jira.mongodb.org/browse/SERVER-1243
It's possible though in MongoDB shell:
db.projectPlan.find({"_id": 1}).forEach(function(plan) {
plan.tasks.forEach(function(task) {
if(task.taskId in { 3: 1, 4: 1 }) {
task.status = "Deleted";
}
});
db.projectPlan.save(plan);
});