How to upsert inside a nested object in mongodb? - node.js

I've a collection named bikes like this:
{
"fname": "foo",
"indian":"hero-corps"
"brands": [
{
"region": "asia",
"type": "terrain"
}
]
}
And getting a json through post like this (let's name it jsonBody):
{
"indian": "hero-corps",
"someKeyA": "someValueA",
}
I'm using the following mongo update query :
db.collection(bikes).update({"indian":"hero-corps"},{$set:jsonBody}, {upsert:true});
The problem is that it's upserting inside the main object, I want to upsert only inside the nested object brands with the jsonBody. How do I achieve that ?
Actual result:
{
"fname": "foo",
"indian": "hero-corps",
"brands": [
{
"region": "asia",
"type": "terrain"
}
],
"indian": "hero-corps",
"someKeyA": "someValueA",
}
Expected result:
{
"fname": "foo",
"indian": "hero-corps",
"brands": [
{
"region": "asia",
"type": "terrain",
"someKeyA": "someValueA",
}
]
}

i'm not sure if that is what you want to do but i'm sure that it will give the format you want.
db.collection(bikes).update({"indian":"hero-corps"},{$push:{"brands":jsonBody}}, {upsert:true});

Related

How to find an id in an array in mongoose using nodejs

I have data something like below:
{
"_id": "60708607143b058e101fc189",
"orders": {
"userID": "606eaa5cf67ac70cfa347fcd",
"order": [
{
"productIDs": [ "606f1f37006513258c8b59b9" ],
"vendorID": "60641cf597aed2a9a2971a3f",
"id": "60708607143b058e101fc18a"
},
{
"productIDs": [ "606f1fec006513258c8b59ba", "606f2bb2006513258c8b59bd" ],
"vendorID": "60642991015028ba0a6ce72c",
"id": "60708607143b058e101fc18b"
}
]
},
}
Is there a way to find any given vendorID in this record using nodejs and mongoose?
If you are logged in as a vendor, then you can send the vendor_id in the body of the request. To filter all orders associated to that particular vendor, you can try this:
Model.find({"orders.order":
{
"$elemMatch": {
"vendorID": req.body.vendor_id
}
}
});

How to rename keys of items in an array

I am very new to MongoDB and I need to do a somewhat complex Update operation on my collection.
I have this kind of collection:
[
{
"Id": 1,
"extension": [
{
"keyName": "Name",
"value": "Bob"
},
{
"keyAge": "Age",
"value": 20
}
]
},
{
"Id": 2,
"extension": [
{
"keyName": "Name",
"value": "Sam"
},
{
"key": "Name",
"value": "Sam"
}
]
},
{
"Id": 3,
"extension": [
{
"keyName": "Age",
"value": 25
},
{
"key": "Age",
"value": 25
}
]
},
{
"Id": 4
}
]
I would like to update any items in the extension array of all documents
so that when an item is found with a key property, to rename it keyAge.
Here is the expected result:
[
{
"Id": 1,
"extension": [
{
"keyName": "Name",
"value": "Bob"
},
{
"keyAge": "Age",
"value": 20
}
]
},
{
"Id": 2,
"extension": [
{
"keyName": "Name",
"value": "Sam"
},
{
"keyAge": "Name",
"value": "Sam"
}
]
},
{
"Id": 3,
"extension": [
{
"keyName": "Age",
"value": 25
},
{
"keyAge": "Age",
"value": 25
}
]
},
{
"Id": 4
}
]
I tried to use $rename in a similar way to this question:
MongoDB rename database field within array
but I get the same error $rename source may not be dynamic array
I think this solution might also apply to me, I tried using it but it's not updating anything on my side, so I guess I cannot understand how to apply that answer to me...
https://stackoverflow.com/a/49193743/215553
Thanks for the help!
I tried to use $rename in a similar way to this question: MongoDB rename database field within array but I get the same error $rename source may not be dynamic array
There is a note in $rename:
$rename does not work if these fields are in array elements.
You can try update with aggregation pipeline starting from MongoDB 4.2,
check condition id key field is exists
$map to iterate loop of extension array
$map to iterate loop of array that is converted from extension object to array in key-value format
$cond check condition if k is key then return keyAge otherwise return current
$arrayToObject back to convert key-value array return from above map to object original format
db.collection.update(
{ "extension.key": { $exists: true } },
[{
$set: {
extension: {
$map: {
input: "$extension",
in: {
$arrayToObject: {
$map: {
input: { $objectToArray: "$$this" },
in: {
k: {
$cond: [
{ $eq: ["$$this.k", "key"] }, // check "key" field name
"keyAge", // update new name "keyAge"
"$$this.k"
]
},
v: "$$this.v"
}
}
}
}
}
}
}
}],
{ multi: true }
)
Playground
Question : How to Rename or add new key for existing array object key?
Answer : Inside projection of mongodb query we have map property which will resolve this.
Solution Example :
{
parents: {
$map: {
input: "$parents",
as: "parent",
in: {
caaUserId: "$$parent._id",
email: "$$parent.email",
countryCode: "$$parent.countryCode",
mobile: "$$parent.mobile",
reportType : "single"
}
}
}
}
In this example if we want to rename $parent._id as caaUserId in parents array for each Element.
Then we can use map and define caaUserId like $$parent._id. This whole code will work in mongoose projection of Query.
It should return following :
{
"parents" : [
{
"caaUserId" : "62d17fa164057000149e283f",
"email" : "john.doe#hotmail.com",
"countryCode" : 91,
"mobile": 9876543210,
"reportType":"single",
},
{
"caaUserId" : "6195d50f15ae2b001293c486",
"email" : "akka.ash#hotmail.com",
"countryCode" : 91,
"mobile": 9876543211,
"reportType":"multi",
},
]
}
This is something that works in your case. Might not be the most readable though.
import json
data = json.loads(strdata)
for entry in data:
if 'extension' in entry:
for x in entry['extension']:
for k, v in x.items():
if k == 'key':
x['keyAge'] = x.pop(k)

How UNSET nested attribute?

I have such document:
{
"name": "FirstObj",
"attributes": {
"my_attributes/601890": {
"value": "Hellow World",
"id": "my_attributes/601890",
"name": "TEstAttr",
"myAttribute": "my_attributes/601890",
"_class": "MyAttributeValue"
}
},
"_class": "MyObj"
}
I cannot write AQL query which unsets "myAttribute": "my_attributes/601890". So i want to get such final document:
{
"name": "FirstObj",
"attributes": {
"my_attributes/601890": {
"value": "Hellow World",
"id": "my_attributes/601890",
"name": "TEstAttr",
"_class": "MyAttributeValue"
}
},
"_class": "MyObj"
}
Note, field attributes is object like key-value.(my_attributes/601890: {}) The field will be huge in the future
You can try to set the value to null and set the options keepNull to false to remove the field during the update.
For item in collection
UPDATE item
WITH {attributes: {"my_attributes/601890": {myAttribute: null}} }
IN collection
OPTIONS { keepNull: false }

Cloudant selector query array field only one get item

How can I get only one item when querying an array on CloudantDB?
Example document :
"category": {
"sub_category": [
{
"category_id": "127"
},
{
"category_id": "128"
}
],
}
query :
{
"selector": {
"sub_category": {
"$elemMatch": {
"category_id": "127"
}
}
}
}
wish result document:
"category": {
"sub_category": [
{
"category_id": "127"
}
],
}
You can't do that with Mango queries. You can accomplish something similar with a combination of a traditional view, and a show function.

How to get filtered result by using Hash Index in ArangoDB?

My data:
{
"rootElement": {
"names": {
"name": [
"Haseb",
"Anil",
"Ajinkya",
{
"city": "mumbai",
"state": "maharashtra",
"job": {
"second": "bosch",
"first": "infosys"
}
}
]
},
"places": {
"place": {
"origin": "INDIA",
"current": "GERMANY"
}
}
}
}
I created a hash index on job field with the API:
http://localhost:8529/_db/_api/index?collection=Metadata
{
"type": "hash",
"fields": [
"rootElement.names.name[*].jobs"
]
}
And I make the search query with the API:
http://localhost:8529/_db/_api/simple/by-example
{
"collection": "Metadata",
"example": {
"rootElement.names.name[*].jobs ": "bosch"
}
}
Ideally, only the document containing job : bosch should be returned as a result. But for me it gives all the documents in the array name[*]. Where I am doing mistake?
Array asterisk operators are not supported by simple queries.
You need to use AQL for this:
FOR elem IN Metadata FILTER elem.rootElement.names.name[*].jobs = "bosch" RETURN elem
You can also execute AQL via the REST interface - However you should rather try to let a driver do the heavy lifting for you.

Resources