Query a list of objects in dynamodb - node.js

I am trying to get a result from my dynamodb database and ran into a problem, I have this data in my orders table.
{
"orders": [
{
"id": "24950-05675",
"orderNumber": null,
"orderProduct": [
{
"id": "28",
"relatedProductsID": null,
"quantity": 1
},
{
"id": "31",
"relatedProductsID": null,
"quantity": 2
},
{
"id": "99",
"relatedProductsID": null,
"quantity": 3
}
]
}
]
}
and I trying to query for the values inside orderProduct attribute as you can see is a list of objects, so am using FilterExpression with contains in my query like this.
productId = {id: '28'}
let attributes = {
country: { String: ':country', Name: 'country', Value: country },
orderProduct: { String: ':orderProduct', Name: 'orderProduct', Value: productId }
};
const { query } = this.generateQueryFull(attributes);
let params = this._createParamObject({
IndexName: 'countryIndex',
KeyConditionExpression: query.string,
ConditionExpression: 'enabled = true',
ExpressionAttributeNames: query.atributeNames,
ExpressionAttributeValues: query.atributeValues,
FilterExpression: 'contains(#orderProduct, :orderProduct)'
});
and running with query like this:
let response = await this.dbService.client
.query(params)
.promise();
The query is generating without problems and the consult is executing correctly.
So the idea is to filter in the list orderProduct by the propertie { id: <string>}, I have done this before without problem with object lists, but when I try this implementation I don't get results but also don't get any error.
I do not know what I can be doing wrong if someone has an idea it would be very helpful.
the final query
query string
{"string":"#country = :country","atributeNames":"#country":"country","#orderProduct":"orderProduct"},"atributeValues":{":country":"co",":orderProduct":{"id":"31"}}}

Related

Dynamodb DB scan: Filter on embedded object in array

Trying to be able to filter on embedded object that looks like:
"posts": [
{
"id": "10e85cf7-acd2-417b-a5dc-1dfb6de606bf",
"references": [
{
"type": "URL",
"title": "How to get dynamodb to only return certain columns",
},
{
"type": "HASHTAG",
"title": "#dynamodb",
},
]
},
...
]
I am trying to return all posts that have reference of type "HASHTAG" and VALUE "#dynamodb". I have tried this but it always returns null (running in node.js):
const params = {
TableName: "tableName",
ScanIndexForward: false,
FilterExpression: "#references.#type = :referenceValue",
ExpressionAttributeNames: {
"#references": "references",
"#type": "HASHTAG"
},
ExpressionAttributeValues: {
":referenceValue": "#dynamoDB"
}
}
const response = await docClient.scan(params).promise();
console.log(response);
And only returns (successfully) an empty array.
Use the contains function to filter on items in a list. In your case, return posts that have an item like :map at the path indicated by #references.
FilterExpression: 'contains(#references, :map)',
ExpressionAttributeNames: { '#references': 'references' },
ExpressionAttributeValues: {
':map': {
type: 'HASHTAG',
title: '#dynamodb',
},
},

Dynamodb scan on array of objects Filter Expression

I want to scan dynamodb using filter on product_id showing in below json of table.
Can anybody explain how to do scanning using filter of product_id.
Wants to scan dynamodb table data using documentclient.
Wants to find all fields which has product_id: something
{
"mandi_id": 1,
"product": [
{
"updated_price": 24,
"product_id": 2,
"last_price": 23
},
{
"updated_price": 24,
"product_id": 5,
"last_price": 23
}
],
"status": "active",
"createdAt": "2022-04-21T08:23:41.774Z",
"mandiCloseTime": "4pm",
"mandi_description": "anaj mandi",
"mandi_name": "gaziabad anaj mandi",
"state": "uttar pradesh",
"city": "gaziabad",
"main_image_s3": "",
"mandi_latlong": {
"lng": 77.48325609999999,
"lat": 28.680346
},
"mandiOpenTime": "10am",
"updatedAt": "2022-04-21T08:23:41.774Z",
"address_name": "gavindpuram",
"landmark_name": "mandi",
"village": "gaziabad",
"postal": "201013"
}
I have tried the following set of code but it is returning empty array list
var params = {
TableName: "dev-agrowave-mandi-management",
// Select: "ALL_ATTRIBUTES"
FilterExpression: "contains(#product,:product)",
ExpressionAttributeNames: {
"#product": "product",
},
ExpressionAttributeValues: { ":product": {"product_id":parseInt(id)}
}
};
let lastEvaluatedKey = 'dummy'; // string must not be empty
const itemsAll = [];
while (lastEvaluatedKey) {
const data = await docClient.scan(params).promise();
itemsAll.push(...data.Items);
lastEvaluatedKey = data.LastEvaluatedKey;
if (lastEvaluatedKey) {
params['ExclusiveStartKey'] = lastEvaluatedKey;
}
}
return {msg:itemsAll,params:params};

Mongodb update all the documents with unique id

I have collection with name products with almost 100k documents. I want to introduce a new key called secondaryKey with unique value uuid in all the documents.
I do this using nodejs.
Problem I am facing:-
When I try the below query,
db.collection('products').updateMany({},{"$set":{secondaryKey: uuid()}});
Here it updates all the documents with same uuid value,
I try with loop to update document one by one,but here issues is I don't have filter value in updateOne because I want to update all the documents.
Can anyone please help me here.
Thanks :)
If you are using MongoDB version >= 4.4 You can try this:
db.products.updateMany(
{},
[
{
$set: {
secondaryKey: {
$function: {
body: function() {
return UUID().toString().split('"')[1];
},
args: [],
lang: "js"
}
}
}
}
]
);
Output
[
{
"_id": ObjectId("..."),
"secondaryKey": "f41b15b7-a0c5-43ed-9d15-69dbafc0ed29"
},
{
"_id": ObjectId("..."),
"secondaryKey": "50ae7248-a92e-4b10-be7d-126b8083ff64"
},
{
"_id": ObjectId("..."),
"secondaryKey": "fa778a1a-371b-422a-b73f-8bcff865ad8e"
}
]
Since it's not the same value you want to put in each document you have to use the loop.
In your loop, you have to update the current document of the iteration. So you have to filter with the _id in the updateOne
The above reply didn't work for me. Plus, it compromises security when you enable javascript on your database (see here $function and javascript enabling on database). The best way is to not overload your server, do your work on local as below:
const { nanoid, customAlphabet } = require('nanoid')
async function asdf() {
const movies = await client.db("localhost").collection("productpost");
var result2 = []
let result = await movies.find({}).toArray()
result.forEach(element => {
const nanoid = customAlphabet('1234567890', 10)
console.log(element.price)
element.price = 4
element.id = nanoid()
result2.push(element)
});
console.log("out reult2", result2)
await movies.deleteMany({})
await movies.insertMany(result2)
})
It will delete any objects on your collections and update with the new ones. Using nanoid as uniqueids.
This is the database object array after adding unique id:
{ "_id": { "$oid": "334a98519a20b05c20574dd1" }, "attach": "[\"http://localhost:8000/be/images/2022/4/bitfinicon.png\"]", "title": "jkn jnjn", "description": "jnjn", "price": 4, "color": "After viewing I am 48.73025772956596% more satisfied with life.", "trademark": "", "category": "[]", "productstate": "Published", "createdat": { "$date": "2022-04-03T17:40:54.743Z" }, "language": "en"}
P.S: Please backup your collection before doing this or filter the array on your needs for not going through all collection.

Multiple conditions in updateOne query in mongodb

Document in mongodb collection 'users' is
{
"$oid": "5e612272bcb362513824ff9b",
"name": "abcd",
"email": "test#test.com",
"cart": {
"items": [{
"productId": {
"$oid": "5e614367cae25319c4388288"
},
"quantity": {
"$numberInt": "1"
}
}]
}
}
For a particular users._id and a productId in cart.items, I need to increase the quantity by 1
My nodejs code is
IncrCartItem(prodId){
const db=getDb()
return db
.collection('users').
updateOne({_id: new mongodb.ObjectId(this._id),'this.cart.items.productId': new mongodb.ObjectId(prodId)},{$inc : {'this.cart.items.quantity':1}})
}
Is the query right for checking multiple conditions in updateOne()??
You're kinda there, to "and" them all together you just keep appending them, however the field is wrong and you need to use the positional operator ($) - https://docs.mongodb.com/manual/reference/operator/update/positional/
const filter = {
_id: new mongodb.ObjectId(this._id),
'cart.items.productId': new mongodb.ObjectId(prodId)
};
const update = {
$inc : { 'this.cart.items.$.quantity': 1 }
};
IncrCartItem(prodId){
const db=getDb()
return db
.collection('users').
updateOne(filter,update)
}

Dynamodb - Update value of JSON object in array of objects

Below is a sample item object/record stored in DynamoDb. I use NodeJS and AWS.DynamoDB.DocumentClient to access the database.
I'm building out a PUT function to update the status for an JSON object in an array. The function will have access to the Item's uuid and room's uuid. How can I simply (creatively) update the value of corresponding status field, given the array of JSON objects?
Params:
let params = {
TableName: room-table,
Key: {
uuid: event.body.uuid
},
UpdateExpression : "??",
ExpressionAttributeNames: {
"??":"??"
},
ExpressionAttributeValues:{
"??":"??"
},
ReturnValues:"ALL_NEW"
};
Item Object:
{
"Item": {
"uuid": "77b1e88e-5e60-44d9-b6ca-aec345c0dc99",
"rooms": [
{
"room": "303",
"status": "pending",
"uuid": "b8f1c1a8-04a9-4c2e-82ad-bc3e81face35"
},
{
"room": "302",
"status": "pending",
"uuid": "42fdc61a-4a25-4316-90c9-60209875d208"
},
{
"room": "678",
"status": "pending",
"uuid": "7bedc115-20ed-4c3e-9cd7-7fed0520f4df"
}
],
"status": "pending"
}
}
It's not possible to do this with ExpressionAttributeValues. I had to build a function to modify the object, similar to below:
function setStatus(jsonObj, uuid, newStatus) {
for (var i=0; i<jsonObj.length; i++) {
if (jsonObj[i].uuid === uuid) {
jsonObj[i].status = newStatus;
return jsonObj;
}
}
}
let params = {
TableName: room-table,
Key: {
uuid: event.body.uuid
},
UpdateExpression : "SET #stat = :stat",
ExpressionAttributeNames: {
"#stat": "status"
},
ExpressionAttributeValues:{
":stat": "updatedStatusValue"
},
ReturnValues:"ALL_NEW"
};
ExpressionAttributeNames is needed because status is a DynamoDB reserved word. More info on Attribute Name and Attribute Value placeholders is available in the DynamoDB docs.

Resources