mongoDB: get field value of an array object - javascript

I want to get the value of the field 30 in the object (in the array test) with the id ePce6fBAHx9KeKjuM.
{
"_id" : "nAwt3b76c24mZfqxz",
"title" : "test",
"test" : [
{
"4" : false,
"15" : false,
"30" : false,
"75" : true,
"id" : "ePce6fBAHx9KeKjuM"
}
]
}
So this result would be false
I tried something like
var result = Collection.findOne({_id: 'nAwt3b76c24mZfqxz'}).test;
But this would give me the complete array. But I need the selected object and only a selected field of this object (ie. 30).

test is just a JS array. Use normal array syntax to access its elements:
var result = Collection.findOne({_id: 'nAwt3b76c24mZfqxz'}).test["30"];
EDIT:
To retrieve the whole object with only 1 element of the array use projection, as of zangw's answer. Following your comment to test element itself:
db.getCollection('a').find(
// put your nested document's condition instead of `$exists`
{_id: 'nAwt3b76c24mZfqxz', test:{ $elemMatch: { "30": {$exists: true}}}},
// add other fields you like to retrieve, e.g. "title":1
{"test.30":1}
)

Try this one
Collection.find({{_id: 'nAwt3b76c24mZfqxz'}}, {'test.30': 1, 'test.id': 1});
To select the whole test array as following without _id
Collection.find({{_id: 'nAwt3b76c24mZfqxz'}}, {'test': 1, '_id': 0});

Related

How to update specific data in array in MongoDB?

{
"_id":{"$oid":"5f5287db8c4dbe22383eca58"},
"__v":0,
"createdAt":{"$date":"2020-09-12T11:35:45.965Z"},
"data":["Buy RAM","Money buys freedom"],
"updatedAt":{"$date":"2020-09-12T11:38:10.637Z"}
}
I want to update the first element in this data array field as Buy SSD.
How can I do it using NodeJS?
db.collection.findOneAndUpdate({
"_id.$oid": "5f5287db8c4dbe22383eca58",
data: "Buy RAM"
}, {
$set: {
"data.$" "Buy SSD"
}
})
This query updates the first element in the data array inside the document that matches "_id.$oid": "5f5287db8c4dbe22383eca58", using $ positional identifier and sets it to the new value.
For more Array Update Operators in mongodb, here is a reference: mongodb manual
You can use filtered positional operator
db.collectionName.updateOne(
{
"_id.$oid": "5f5287db8c4dbe22383eca58"
},
{
$set: {
"data.$[element]": "Buy SSD"
}
},
{
{ arrayFilters: [ { element: "Buy Ram" } ] }
})
Caution: It will update all array element matching the text. In this case, "Buy Ram"
You can use str.replace()
var product =
[{
"_id":{"$oid":"5f5287db8c4dbe22383eca58"},
"__v":"0",
"createdAt":{"$date":"2020-09-12T11:35:45.965Z"},
"data":["Buy RAM","Money buys freedom"],
"updatedAt":{"$date":"2020-09-12T11:38:10.637Z"}
}]
var new_product = JSON.stringify(product).replace("Buy RAM", "Something");
console.log(new_product);
UpdateOne -> Updates a single Document:
db.collection.updateOne(filter, update, options)
You will probably gonna filter using the _id field, and use $set to update the specific field.
Use the dot-notation to access and set fields deep inside objects, without affecting the other properties of those objects.
you want to update the 1st array entry in "data", and array keys are 0 indexed - that's the key 0.
so the query will look something like that:
db.collection.update(
{ _id: { "$oid": "56476e04e5f19d86ece5b81d"}, // probb ObjectId Instance
{ $set:
{
"data.0": "Buy SSD" // Using dot-notation
}
}
)
for more advanced use, you can use the MongoDB's positional operator $ without explicitly specifying the position of the element in the array.
The positional operator allows you to use a condition like this:
{"Order.name": "test"}
and then reference the found array entry like so:
{"Order.$ // <- the dollar represents the first matching array key index
Example:
/* DATA
{
"_id" : "43434",
"Order" : [
{"name" : "test", "items" : ["", "new_value", "" ]},
{"name" : "test2", "items" : ["", "", "" ]}
]
}
*/
db.collection.update(
{ _id: "43434", "Order.name": "test2"},
{ $set:
{
"Order.$.items.1": "new_value2" // positional operator & dot-notation.
}
}
)
>>> db.collection.find()
{
"_id" : "43434",
"Order" : [
{"name" : "test", "items" : ["", "new_value", "" ]},
{"name" : "test2", "items" : ["", "new_value2", "" ]}
]
}

Mongodb native driver chain queries

I am new to queries in mongodb. I have a document like this -
{
"_id" : ObjectId("5eb0f70f88cd051e7839325c"),
"id" : "1",
"arrayInfo" : [ {"color":"red"}, {"color":"black"}, {"color":"cyan"} ]
}
There are many documents in this format with changing ids and colors inside arrayInfo. I want to do something like -
Find record with id "1" -> Display object inside array info with {"color" : "cyan"}
I believe I have to chain queries after finding like this -
db.collection('Records').findOne({id:"1"}).**something**
Any help will be appreciated thanks.
if(id===1){
res.arrayInfo.map(item => console.log(item.color))
}
db.inventory.find( { "instock": { $elemMatch: { qty: 5, warehouse: "A" } } } )
enter link description here
If no operator is specified, MongoDB by default performs array element matching when the document stores an array. Thus you can simply do:
MongoDB Enterprise ruby-driver-rs:PRIMARY> db.foo.findOne({id:'1',arrayInfo:{color:'cyan'}})
{
"_id" : ObjectId("5eb0f70f88cd051e7839325c"),
"id" : "1",
"arrayInfo" : [
{
"color" : "red"
},
{
"color" : "black"
},
{
"color" : "cyan"
}
]
}
To match one field in the array instead of the complete array element, use $elemMatch.

Mongoose find returns document instead of specific object in array

When I try to find specific object in array using find({query}) I always get all elements from array.
Activities array stores activities (it would be a thousands of them) as you can see in the following snippet:
This is my collection:
{
"_id" : ObjectId("58407140755324d04db2ce95"),
"owner" : 103429326776572,
"activities" : [
{
"name" : "test1",
"startTime" : ISODate("2016-08-11T17:41:54Z"),
"type" : "te1",
"lat" : 1,
"lon" : 1,
"creator" : 126212904493088,
"coverPhoto" : {
"name" : "test1",
"path" : "c:\\Users\\Francis\\Desktop\\dusk\\public\\coverPhotos\\SJ9tpP6Mx.jpg"
},
"identifier" : "H1g9F6vpGl",
"users" : [
1,
2,
3
],
"hashTags" : [
"some",
"hashtags"
]
},
{
"name" : "test2",
"startTime" : ISODate("2016-08-11T17:41:53Z"),
"type" : "te2",
"lat" : 1,
"lon" : 1,
"creator" : 103312904493090,
"coverPhoto" : {
"name" : "test2",
"path" : "c:\\Users\\Francis\\Desktop\\dusk\\public\\coverPhotos\\Hy8qpvafe.jpg"
},
"identifier" : "rJlU5TvpMx",
"users" : [
1,
2,
3
],
"hashTags" : [
"some",
"hashtags"
]
}
]
}
I need to get for example an activity that has specific identifier.
I tried to use queries like:
1) db.myCollection.find({'activities.identifier' : "rJlU5TvpMx"})
2) db.myCollection.find({'activities' : { $elemMatch : { "identifier" : "rJlU5TvpMx", "creator" : 103312904493090 } })
And all combinations with '' or "" signs
I found above queries at mongodb docs in equal documents schema as mine is.
Can you tell me what am I doing wrong ?
You can try either use single match or multiple match based on your need. This makes use of $elemMatch(projection)
db.myCollection.find({"_id" : ObjectId("58407140755324d04db2ce95")},
{activities: {$elemMatch: { identifier: "rJlU5TvpMx"}}})
db.myCollection.find( {"_id" : ObjectId("58407140755324d04db2ce95")},
{activities: {$elemMatch: {creator : 103312904493090, identifier: "rJlU5TvpMx" }}})
You are looking for the projection object which gets passed as an argument in your query. It allows the return of specific fields from your search rather than the entire document. http://mongoosejs.com/docs/api.html#model_Model.find
I would also suggest looking at the response to this question here: Mongoose Query: Find an element inside an array which makes use of the unwind operator to enter the array as it seems to be relevant to your needs.
In the collection you are searching in, you have just one Document(Object). If you apply method find() to your collection and the query inside matches the value in activities.identifier it will return the only Document(object).
To have a better understanding of what I am talking about check example on mongoose API doc
And query result here.
Try check this out https://docs.mongodb.com/v3.0/reference/operator/projection/elemMatch/#proj._S_elemMatch instead

Updating an array object creates a new empty object

I have an array of orders containing user ID, the amount and the order itself. Each user can only have one order at a time but I'm trying to add an option to edit your order. I created a method that is supposed to be doing that:
'click .edit': function (event) {
var order = $('#editOrder').val();
var price = $('#editPrice').val();
Meteor.call('changeOrder', Router.current().data()._id, Meteor.userId(), order, price);
Session.set("editing", false);
},
changeOrder: function (id, user, order, amount) {
Polls.update({_id: id, 'Orders.User': user}, {$set: {'Orders.$': {
User: user,
Order: order,
Amount: parseFloat(amount)
}}});
},
This method actually works but the problem is every time I edit an order it creates a new object with the same user ID and empty Order and Amount properties.I honestly have no idea what could be causing an update function to insert void data.
Here's an example of the Poll structure with the extra empty order:
{
"_id" : "4wGAPfxCvKfH4L8JL",
"Company" : "FirmaTest",
"Restaurants" : [
"Trylinka",
"Da Grasso",
"Faster",
"Green Way",
"Telepizza",
"Piramida"
],
"Expires" : ISODate("2015-08-24T08:26:00.791Z"),
"Votes" : {
"Trylinka" : 1,
"Da Grasso" : 0,
"Faster" : 2,
"Green Way" : 3,
"Telepizza" : 0,
"Piramida" : 0
},
"Voted" : [
"TfQM7954a5SHoR9os"
],
"Winner" : "Green Way",
"Orders" : [
{
"User" : "TfQM7954a5SHoR9os",
"Order" : "Some chicken",
"Amount" : 15
},
{
"User" : "TfQM7954a5SHoR9os",
"Order" : null,
"Amount" : NaN
}
],
"Ordered" : [
"TfQM7954a5SHoR9os"
]
}
Solved
Turns out I was triggering a submit form located in the same page. Even though the event I was calling wasn't a 'form submit' it had a form in it and so the submit still went through. Also I used the same variable names in both the form submit and the button trigger so the insert methods still went through.
Thanks for the answers but it turns out the problem was somewhere else and my fault entirely :)
Is it possible you are querying _id with a string instead an ObjectID?
Try converting the id into an ObjectID with:
new Meteor.Collection.ObjectID(valuefromhtml)
So your code will be:
Polls.update({
_id: new Meteor.Collection.ObjectID(id),
'Orders.User': user
}, {
$set: {
'Orders.$': {
User: user,
Order: order,
Amount: parseFloat(amount)
}
}
});
Not sure what that bug is, but you have no need for "overwriting" your entire object with that update, which could be what causes this. You can just update the only two properties that are actually subject to change:
Polls.update(
{_id: id, 'Orders.User': user},
{$set:
{'Orders.$.Order': order, 'Orders.$.Amount': parseFloat(amount)}
}
);
Try to set upsert to false:
Polls.update({_id: id, 'Orders.User': user},
{$set:
{'Orders.$':
{
User: user,
Order: order,
Amount: parseFloat(amount)
}
}
},
{ upsert: false });
If this don't work, try with upsert: false on BraveKenny's answer.
I hope this helps.

How to make MongoDB find nested json return as an array?

I have this data:
{
"_id" : ObjectId("5461e16ee7caf96f8f3584a2"),
"num_marcacao" : "100",
"sexo" : "Fêmea",
"idade" : "20",
"bigdata" : {
"abortos" : [
{
"data_aborto" : "2014-11-11",
"causa_aborto" : "Aborto causa 1"
},
{
"data_aborto" : "2014-09-01",
"causa_aborto" : "Aborto causa 2"
}
],
"crias" : [
ObjectId("5461e16ee7caf96f8f3584a2")
]
}
}
{
"_id" : ObjectId("5461e1cae7caf96f8f3584a4"),
"num_marcacao" : "200",
"sexo" : "Fêmea",
"bigdata" : {
"crias" : [
ObjectId("5461e1f3e7caf96f8f3584a5"),
ObjectId("5461e760e7caf96f8f3584a6")
]
}
}
Using the following distinct function I get one result
db.animal.distinct('_id', {'bigdata.crias':{$exists:true}}
Result:
{
"0" : ObjectId("5461e16ee7caf96f8f3584a2"),
"1" : ObjectId("5461e1cae7caf96f8f3584a4")
}
Now I want to get the array that is in bigdata.crias like the result of the distinct query.
I'm trying to do like this:
db.animal.find(
{
$and: [
{'num_marcacao': '200'},
{'bigdata.crias':{$exists: true}}
]
},
{
'bigdata.crias': true,
'_id': false
}
)
But the result is not like the one I need. This is what it's returning:
{
"bigdata" : {
"crias" : [
ObjectId("5461e1f3e7caf96f8f3584a5"),
ObjectId("5461e760e7caf96f8f3584a6")
]
}
}
And I need
{
"0" : ObjectId("5461e1f3e7caf96f8f3584a5"),
"1" : ObjectId("5461e760e7caf96f8f3584a6")
}
Anyhow. MongoDB does not generally do this from either the .find() or .aggregate() methods or anything general around them. Only the .distinct() method invokes a special form where the result given is "truly" just an array of the specified "key" to be distinct on.
You can always "inspect" the object returned and just use the array element in the structure. You can also specify a "query" argument to the .distinct() command method in the first place:
db.collection.distinct(
"bigdata.crias",
{
"bigdata.crias": { "$exists": true },
"num_marcacao": "200"
}
);
Where you also see your $and argument is redundant. All MongoDB query arguments are an "and" implementation by default. You don't need this unless you are specifying "more than one" condition on the same "field name". That would result in an invalid object by breaking the basic "hash/map" "unique key" rule, and which is why and "array" is used for this form to keep it valid.

Categories

Resources