MongoDB add values to array if not exists - arrays

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/

Related

MongoDb: search only if it contains all ids within the array

I am looking for an array of ids, inside another array, the problem is that if it contains at least one "id" it returns the result. The validation should be that it has to have all the "ids" that I am passing.
{ subcategories: { $in: [ ObjectId('61729d550e8fe20011cc57d2', ObjectId('61693f589a34340012b1d5d8'), ObjectId('61693f2c9a34340012b1d5b7') )] } }
example:
subcategories: ["61729d550e8fe20011cc57d2", "61693f2c9a34340012b1d5b7"] -> this one should not appear, because it contains only 2 of the 3 I am looking for
I think you are looking for $all.
The docs says:
The $all operator selects the documents where the value of a field is an array that contains all the specified elements
db.collection.find({
subcategories: {
$all: [
"61729d550e8fe20011cc57d2",
"61693f589a34340012b1d5d8",
"61693f2c9a34340012b1d5b7"
]
}
})
Example here

How to specify multiple nested documents in mongoimport?

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:

update field of array object inside nested object

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

Fetch specific array elements from a array element within another array field in mongodb

My document structure is as below.
{
"_id" : {
"timestamp" : ISODate("2016-08-27T06:00:00.000+05:30"),
"category" : "marketing"
},
"leveldata" : [
{
"level" : "manager",
"volume" : [
"45",
"145",
"2145"
]
},
{
"level" : "engineer",
"volume" : [
"2145"
]
}
]
}
"leveldata.volume" embedded array document field can have around 60 elements in it.
In this case, "leveldata" is an array document.
And "volume" is another array field inside "leveldata".
We have a requirement to fetch specific elements from the "volume" array field.
For example, elements from specific positions, For Example, position 1-5 within the array element "volume".
Also, we have used positional operator to fetch the specific array element in this case based on "leveldata.level" field.
I tried using the $slice operator. But, it seems to work only with arrays not with array inside array fields, as that
is the case in my scenario.
We can do it from the application layer, but that would mean loading the entire the array element from mongo db to memory and
then fetching the desired elements. We want to avoid doing that and fetch it directly from mongodb.
The below query is what I had used to fetch the elements as required.
db.getCollection('mycollection').find(
{
"_id" : {
"timestamp" : ISODate("2016-08-26T18:00:00.000-06:30"),
"category" : "sales"
}
,
"leveldata.level":"manager"
},
{
"leveldata.$.volume": { $slice: [ 1, 5 ] }
}
)
Can you please let us know your suggestions on how to address this issue.
Thanks,
mongouser
Well yes you can use $slice to get that data like
db.getCollection('mycollection').find({"leveldata.level":"manager"} , { "leveldata.volume" : { $slice : [3 , 1] } } )

$set operator interpreting array index as object index in mongodb

MongoDB seems to interpret $set paths with numerical components as object keys rather than array indexes if the field has not already been created as an array.
> db.test.insert({_id: "one"});
> db.test.update({_id: "one"}, {$set: {"array.0.value": "cheese"}});
> db.find({_id: "one"})
{ "_id": "one", "array": { "0" : { "value" : "cheese" } }
I expected to get "array": [{"value": "cheese"}], but instead it was initialized as an object with a key with the string "0".
I could get an array by initializing the whole array, like so:
> db.test.update({_id: "one"}, {$set: {"array": [{"value": "cheese"}]}});
... but this would clobber any existing properties and other array elements that might have been previously set.
Is there any way to convince $set that I want "array" to be an array type, with the following constraints:
I want to execute this in a single query, without looking up the record first.
I want to preserve any existing array entries and object values
In short, I want the behavior of $set: {"array.0.value": ... } if "array" had already been initialized as an array, without knowing whether or not it has. Is this possible?
I am not sure if this is possible without lookup. Perhaps you can change schema design, and try something like this:
db.test.insert({_id: "one"});
db.test.update({_id: "one"}, {$addToSet: {array: { $each:['cheese', 'ham'] }}});
db.test.findOne({_id:'one'});
// { "_id" : "one", "array" : [ "cheese", "ham" ] }
Handling array elements (sub-documents in array) in MongoDb is pain. https://jira.mongodb.org/browse/SERVER-1243

Resources