Deleting Object from Nested Array MongoDB - database

I am trying to delete the object with the id: "2019-08-22T04:53:11.357Z" from this users portfolio array.
I have searched for the correct query filter to help me delete the object but nothing seems to be working!
Here is the data we are working with. There is currently only one user
(InStock) in the system but more will be added in the future.
[
{
"id": "MTg4MDU3ODM2MDk2NDU0NjU3",
"name": "InStock",
"balance": 7760,
"portfolio": [
{
"id": "2019-08-22T04:15:22.998Z",
"name": "Jordan Shoe",
"size": "10.5",
"price": 150
},
{
"id": "2019-08-22T04:36:37.836Z",
"name": "Nike Tee",
"size": "M",
"price": 35
},
{
"id": "2019-08-22T04:53:11.357Z",
"name": "Adidas Shoe",
"size": "8.5",
"price": 100
}
],
"history": [
]
}
]
and here is what I was trying using what I've seen in other solutions.
db.collection(collectionName).updateOne({"id": "MTg4MDU3ODM2MDk2NDU0NjU3"}, {$pull : {"portfolio": {"id": "2019-08-22T04:36:37.836Z"}}})
I am looking for the line to remove the Adidas Shoe object from InStock's portfolio array.

Try this query:
db.test1.updateOne({"_id" : ObjectId("5d5e7a291b761bfc0420e580")},
{$pull: {"portfolio": {"name": "Adidas Shoe"}}} )
After execution:
{
"_id" : ObjectId("5d5e7a291b761bfc0420e580"),
"portfolio" : [
{
"id" : "2019-08-22T04:15:22.998Z",
"name" : "Jordan Shoe",
"size" : "10.5",
"price" : 150.0
},
{
"id" : "2019-08-22T04:36:37.836Z",
"name" : "Nike Tee",
"size" : "M",
"price" : 35.0
}
],
"name" : "InStock",
"balance" : 7760.0
}

It's Working Fine for you.
db.collection(collectionName).updateOne({"id": "MTg4MDU3ODM2MDk2NDU0NjU3"},
{ $pull: { portfolio: { $elemMatch: { id:"2019-08-22T04:36:37.836Z"} }},

Related

Creating 1-1 mapping of Array results

I am trying to use data coming back from an ElasticSearch query, and get it into an Array in jsonata in a certain format.
Essentially, I need my result set to be like this:
{
"userName": [
"david2#david2.com",
"david2#david2.com",
"david2#david2.com",
"david2#david2.com"
],
"label": [
"Dealer",
"Inquiry",
"DD Test Skill1",
"_11DavidTest"
],
"value": [
3,
5,
2,
1
]
}
However, what I am getting is this:
{
"userName": "david2#david2.com",
"label": [
"Dealer",
"Inquiry",
"DD Test Skill1",
"_11DavidTest"
],
"value": [
3,
5,
2,
1
]
}
I am using the following to map the results:
(
$data := $map(data.hits.hits._source.item."Prod::User", function($v) {
{
"userName": $v.userName,
"label": $v.userSkillLevels.skill.name,
"value": $v.userSkillLevels.level
}
});
)
And my overall dataset returned form ElasticSearch is as follows:
{
"data": {
"took": 3,
"timed_out": false,
"_shards": {
"total": 15,
"successful": 15,
"skipped": 0,
"failed": 0
},
"hits": {
"total": {
"value": 2,
"relation": "eq"
},
"max_score": 1.002851,
"hits": [
{
"_index": "items_latest_production1_user",
"_type": "_doc",
"_id": "63d000766f67d40a73073d5d_f6144acf2b3ff31209ef9f6d461cd849",
"_score": 1.002851,
"_source": {
"item": {
"Prod::User": {
"userSkillLevels": [
{
"level": 3,
"skill": {
"name": "Dealer"
}
},
{
"level": 5,
"skill": {
"name": "Inquiry"
}
},
{
"level": 2,
"skill": {
"name": "DD Test Skill1"
}
},
{
"level": 1,
"skill": {
"name": "_11DavidTest"
}
}
],
"userName": "david2#david2.com"
}
}
}
}
]
}
}
}
I can see that each user that comes back from Elastic, then as all the skills/levels in an array associated to 1 username.
I need to have the same number of userNames, as their are skills ... and am struggling to get it just right.
Thoughts? Appreciate any help, I'm sure I'm overlooking something simple.
Actually, need this format:
[
{
"userName" : "david2#david2.com"
"label" : "Dealer"
"value" : 3
},
{
"userName" : "david2#david2.com"
"label" : "Inquiry"
"value" : 5
},
{
"userName" : "david2#david2.com"
"label" : "DD Test Skill"
"value" : 2
},
{
"userName" : "david2#david2.com"
"label" : "_11DavidTest"
"value" : 1
}
]
One way you could solve this is to create the userName array yourself and making sure it has the same length as userSkillLevels.skill, here's how you can do this:
(
$data := $map(data.hits.hits._source.item."Prod::User", function($v, $i, $a) {
{
"userName": $map([1..$count($v.userSkillLevels.skill)], function() {$v.userName}),
"label": $v.userSkillLevels.skill.name,
"value": $v.userSkillLevels.level
}
});
)
Feel free to check out this response in Stedi JSONata Playground: https://stedi.link/PVwGacu
Actually, need this format:
For the updated format from your question, this solution can produce it using the parent operator:
data.hits.hits._source.item."Prod::User".userSkillLevels.{
"userName": %.userName,
"label": skill.name,
"value": level
}
Check it out on the playground: https://stedi.link/gexB3Cb

JSON Schema: First Item of Array

I need a JSON array of arbitrary length. Each item in the array is a JSON object, they all have same keys and types.
But the schema should make one exception: the first object doesn't need all keys, so schemas required list should be shorter for the first item.
I tried schemas with "items" and "prefixItems" without luck. It seems that "prefixItems" will be ignored independently of draft version when used with "items". Because array can be of arbitrary length, I guess I cannot use multiple schemas with "items".
{
"description": "Schema for array data",
"$schema": "http://json-schema.org/draft-2020-12/schema#",
"version": "0-0-6",
"type": "object",
"required": [
"data"
],
"properties": {
"data": {
"type": "array",
"prefixItems": [{
"type": "object",
"required": [
"name"
],
"properties": {
"name" : { "type" :"string" },
"age" : { "type" : "number" },
"city" : { "type" : "string" }
}
}],
"items":
{
"type": "object",
"required": [
"name", "age", "city"
],
"properties": {
"name" : { "type" :"string" },
"age" : { "type" : "number" },
"city" : { "type" : "string" }
}
}
}
}
}
My data:
{
"data" : [
{
"name": "Tom"
},
{
"name": "Ben",
"age": 32,
"city": "Berlin"
},
{
"name": "Mike",
"age": 40,
"city": "Boston"
}
]
}
For validation I use:
https://www.jsonschemavalidator.net/
https://jsonlint.com/
Validation of my example gives error for first item:
"Required properties are missing from object: age, city."
Use additionalItems instead of items.
Schema:
{
"$schema": "https://json-schema.org/draft/2020-12/schema",
"type": "array",
"prefixItems": [
{ "type": "number" },
{ "type": "string" },
{ "enum": ["Street", "Avenue", "Boulevard"] },
{ "enum": ["NW", "NE", "SW", "SE"] }
],
"additionalItems": {
"type": "number"
}
}
Data that validates:
[
1600,
"Pennsylvania",
"Avenue",
"NW",
1]
The issue you're running into is that the validators only support up to draft 7 of the standard, and using items the way we both want to was new in the 2019 draft. It's not supported yet.

How to add fields in array list in mongo db

{
"_id" : "1",
"teams" :
[
{
"type" : "local",
"isEnabled" : "true",
"names" :
[
{ "name": "kumar","Nationality":"indian","BirthPlace":"Goa","Age":"U25" },
{ "name": "kannan","Nationality":"indian","BirthPlace":"Kerala","Age":"U25"}
]
},
{
"type" : "national",
"isEnabled" : "true",
"names" :
[
{ "name": "kumar","Nationality":"indian","BirthPlace":"Goa","Age":"U25" },
{ "name": "kannan","Nationality":"indian","BirthPlace":"Kerala","Age":"U25"}
]
},
{
"type" : "international",
"isEnabled" : "true",
"names" :
[
{ "name": "kumar","Nationality":"indian","BirthPlace":"Goa","Age":"U25" },
{ "name": "kannan","Nationality":"indian","BirthPlace":"Kerala","Age":"U25"}
]
},
]
}
I have multiple docs in the same format in a mongodb collection. I wanted to append the below lines into names array also only for "type: local" in each docs of the collections. I tried $push and its appending in all teams array as i am finding difficulty to add this condition only for "type":"local"
{
"name":"jack","Nationality":"indian","BirthPlace":" "Karnataka","Age":"U25"
}
You can use positional operator : $[]
db.collection.update({
"teams.type": "local"
},
{
$push: {
"teams.$[element].names": {
"name": "jack",
"Nationality": "indian",
"BirthPlace": "Karnataka",
"Age": "U25"
}
}
},
{
arrayFilters: [
{
"element.type": "local"
}
],
multi: true
})
Try it here

How to get a value in one mongodb collection and use that value to update another document in another collection order & inventory system

Hello I have been stuck for weeks trying to figure how to create a order & inventory system for a project I am working on. I don't know how to properly ask this but my problem is when a user adds items to their cart > I store the order details in a orders collection in mongodb > I then need to figure out how to subtract the quantity of the items in a customers order from my inventory collection. How can I do this with mongodb, Python
This is the document created when a customer places an order
{
"_id": "5eca94b4f56331fd9eade681",
"ordernumber": 343,
"order": {
"order_details": [
{
"customer_info": [
{
"first_name": "John",
"last_name": "Doe",
"email": "email#email.com"
}
],
"shipping_details": [
{
"shipping_address": "Test Address",
"shipping_zip": "12345",
"shippingl_city": "Test city",
"shipping_country": "USA"
}
],
"products_ordered": [
{
"variant_id": "a",
"product_name": "red shirt",
"price": 30,
"quantity": 2,
"image": "imageurl",
"size": "Small"
},
{
"variant_id": "f",
"product_name": "Blue Jeans",
"price": 20,
"quantity": 3,
"image": "imageurl",
"size": "Large"
}
]
}
]
}
}
These are the products in my inventory collection I want inventory order quantity subtracted by the quantity a customer purchased
{
"_id": "5eca0ff4898b8f30a9fee5e5",
"product_id": 1,
"product_name": "red shirt",
"category": "shirts",
"price": 30,
"status": "instock",
"description": "nice red shirt",
"alt": "string",
"images": [
"imageUrl1",
"imageUrl2"
],
"variants": [
{
"Small": [
{
"variant_id": "a",
"inventory": 30
}
],
"Medium": [
{
"variant_id": "b",
"inventory": 10
}
],
"Large": [
{
"variant_id": "c",
"inventory": 10
}
]
}
]
}
{
"_id": "5eca108f898b8f30a9fee5e6",
"product_id": 2,
"product_name": "blue jeans",
"category": "jeans",
"price": 20,
"status": "instock",
"description": "nice blue jeans",
"alt": "string",
"images": [
"ImageURL"
],
"variants": [
{
"Small": [
{
"variant_id": "d",
"inventory": 100
}
],
"Medium": [
{
"variant_id": "e",
"inventory": 150
}
],
"Large": [
{
"variant_id": "f",
"inventory": 70
}
] }
]
}
I would suggest to do it along with the service which creates the order.
I would also like to suggest to refactor the db structure a bit as it would be harder to maintain this in a larger scale.
Because currently we would have to write something like
for ordered_product in products_ordered:
query = { "product_name": ordered_product.get("product_name") }
inventory_product = inventory_collection.find_one(query)
product_id = inventory_product["_id"]
existing_count = inventory_product["variants"][0][ordered_product.size][0]["inventory"]
inventory_product["variants"][0][ordered_product["size"]][0]["inventory"] = existing_count - ordered_product["quantity"]
inventory_collection.update_one({ "_id": product_id }, { "$set": inventory_product })
I have hardcoded the index values of the list. You could use filter() to filter out the variant and size you need.
This code definitely seems messy to me.
Of course you could refactor this code by splitting it into functions inside the model file itself, but I would suggest to refactor the db structure for better scalability.
May be you could move the variants to a seperate collection and use the product_id as a link. You have to think this through before getting on with the code.
Hope this helps.

Pushing Values from JSON Object into Array

I have the following object in my AngularJS Controller:
{"team":"1","name":"abc","age":"20"},
{"team":"1","name2":"def","age2":"21"},
{"team":"2","name":"ghi","age":"22"},
{"team":"2","name2":"jkl","age2":"23"},
I need to group the items into one array object, by the team key.
{
"team": [
{"name1":"abc","age1":"20", "name2":"def", "age2":"21"},
{"name1":"ghi","age1":"22", "name2":"jkl", "age2":"23"}
]
}
So I can later use the information like $scope.data.team[1].name2
EDIT: One Team always consists of 4 players by the way.
How would I do this?
edit: working plunkr for your needs: http://plnkr.co/edit/zxoOYV?p=preview
you should rearrange your structure. i.e. you could go for something like this:
{"team": [
{"players": [
{"name" : "abc", "age": 20},
{"name" : "def", "age": 34},
]},
{"players": [
{"name" : "abc", "age": 20},
{"name" : "def", "age": 34},
]}
]}
if you use this structure in your controller:
$scope.team = {...}
and use it in your html like:
<div ng-controller="TeamController">
<div ng-repeat="players in team">
<div ng-repeat="player in players">
<div>Name: {{player.name}}</div>
<div>Name: {{player.age}}</div>
</div>
</div>
</div>
so, for your example, i got the angular-schema-form working.
with the above structure the schema looks like this:
[
{
"type": "help",
"helpvalue": "<h4>Tabbed Array Example</h4><p>Tab arrays can have tabs to the left, top or right.</p>"
},
{
"key": "team",
"type": "tabarray",
"add": "New",
"remove": "Delete",
"style": {
"remove": "btn-danger"
},
"title": "value.name || 'Team '+$index",
"items": [
{
"key": "team[].players",
"title": "Players",
"items": [
{
"key": "team[].players[].name",
"title": "Name"
},
{
"key": "team[].players[].age",
"title": "Age"
}
]
}
]
},
{
"type": "submit",
"style": "btn-default",
"title": "OK"
}
]
and the corresponding schema:
{
"type": "object",
"title": "Team",
"properties": {
"team": {
"type": "array",
"items": {
"type": "object",
"properties": {
"players": {
"type": "array",
"maxItems": 4,
"items": {
"type": "object",
"properties": {
"name": {
"type": "string"
},
"age": {
"type": "integer"
}
},
"required": [
"name",
"age"
]
}
}
},
"required": [
"players"
]
}
}
}
}

Resources