I have a Players collection and a Games collection. I want to construct a data structure that looks as follows:
{
"_id": "1234",
"accounts": {
"battlenet": "blah#1234"
},
"games": {
"overwatch": {
"class": "Hanzo",
"timePlayed": ISODate
},
"world-of-warcraft": {
"class": "Shaman",
"timePlayed": ISODate
}
}
}
games is an object, where every key refers to a specific document in the Games collection's slug attribute. Every value is a sub-schema definition with autoValues.
I can't find any good way to create validation in such a way that it updates an autoform correctly without weird coersion of data. Is there any way to accomplish this validation with simple schema?
Related
So if I have an object, let's call it a Person, like:
{
"email": "foo#bar.com",
"first"" "foo",
"last": "bar"
}
This Person object can all be validated quite well with JSON Schema. The issue is when multiple of these are arranged into a dictionary where the email field is used as the key and the object is the value. For example:
{
"foo#bar.com": {
"email": "foo#bar.com",
"first"" "foo",
"last": "bar"
},
"you#your.com": {
"email": "you#your.com",
"first": "Bob",
"last": "Bobton"
},
"me#mine.com": {
"email": "me#mine.com",
"first": "Deb",
"last": "Debbington"
}
}
This is a common way to structure data. Beyond the validation of the Person values, which can be handled well by a JSON Schema, there are a number of validations that would be useful on the dictionary:
The key is an email and can be validated as one.
The value is always a Person.
The key is always identical to the value's email field.
All the keys are unique.
Is it possible to implement these dictionary validations using JSON Schema?
The first two requirements, yes.
You can use patternProperties.
The other two you ask are not possible using JSON Schema. Sorry.
My expectation would be you receive the data in the first form from an API, validate, then map reduce to your desired structure.
How to insert data in to datastore?
The data could be like the one below:
{
'food': [{
"item_name": item,
'price': price
}, {
"item_name": item,
'price': price
}],
'beverages': [{
''
'beverage_name': beverage,
'beverage_price': b_price
}, {
''
'beverage_name': beverage,
'beverage_price': b_price
}]
}
The data that you are trying to add to the Google Cloud Datastore is a JSON string. The way you have it in your question is wrong structured. The proper JSON example would be:
{
"food": [
{ "food_name":"NAME1", "food_price":"PRICE1" },
{ "food_name":"NAME2", "food_price":"PRICE2" },
{ "food_name":"NAME3", "food_price":"PRICE3" }
],
"beverages":[
{ "beverage_name":"NAME1", "beverage_price":"PRICE1" },
{ "beverage_name":"NAME2", "beverage_price":"PRICE2" }
]
}
To add the data from the JSON string to the Datastore you have to:
Load the JSON string as JSON object to be able to go through its fields
Create a client to access Google Datastore
Set the key food for the Kind value in Datastore
Use the entity to add the data to the Datastore
Set the key beverages for the Kind value in Datastore
Use again entity to add the data to the Datastore
For further information, you can refer to Google Cloud Data Store Entities, Properties, and Keys documentation.
I have done a little bit coding myself and here is my code example in GitHub for Python. You can take the idea of how it works and test it. It will create two different Kind values in Datastore and add the food data in foods and beverage data to beverages.
Consider the following document item / syntax in a DynamoDB table:
{
"id": "0f00b15e-83ee-4340-99ea-6cb890830d96",
"name": "region-1",
"controllers": [
{
"id": "93014cf0-bb05-4fbb-9466-d56ff51b1d22",
"routes": [
{
"direction": "N",
"cars": 0,
"sensors": [
{
"id": "e82c45a3-d356-41e4-977e-f7ec947aad46",
"light": true,
},
{
"id": "78a6883e-1ced-4727-9c94-2154e0eb6139",
}
]
}
]
}
]
}
My goal is to update a single attribute in this JSON representation, in this case cars.
My approach
I know all the sensors IDs. So, the easiest way to reach that attribute is to find, in the array, the route which has a sensor with any of the ids. Having found that sensor, Dynamo should know which object in the routes array he has to update. However, I cannot run this code without my condition being rejected.
In this case, update attribute cars, where the route has a sensor with id e82c45a3-d356-41e4-977e-f7ec947aad46 or 78a6883e-1ced-4727-9c94-2154e0eb6139.
var params = {
TableName: table,
Key:{
"id": "0f00b15e-83ee-4340-99ea-6cb890830d96",
"name": "region-1"
},
UpdateExpression: "set controllers.intersections.routes.cars = :c",
ConditionExpression: ""controllers.intersections.routes.sensors.id = :s",
ExpressionAttributeValues:{
":c": 1,
":s": "e82c45a3-d356-41e4-977e-f7ec947aad46"
},
ReturnValues:"UPDATED_NEW"
};
docClient.update(params, ...);
How can I achieve this?
Unfortunately, you can't achieve this in DynamoDB without knowing the array index. You have very complex nested structure. The DynamoDB API doesn't have a feature to handle this scenario.
I think you need the array index for controllers, routes and sensors to get the update to work.
Your approach may work in other databases like MongoDB. However, it wouldn't work on DynamoDB. Generally, it is not recommended to have this complex structure in DynamoDB especially if your use case has update scenario.
TableName : 'tablename',
Key : { id: id},
ReturnValues : 'ALL_NEW',
UpdateExpression : 'set someitem['+`index`+'].somevalue = :reply_content',
ExpressionAttributeValues : { ':reply_content' : updateddata }
For updating nested array element need to fing out array index . Then you can update nested array element in dynamo db.
I have the following situation:
I have a team entity, in each team we have one or more users.
At first I thought about creating an array of IDS inside team. And then download all team and use the javascript to go through these IDS and fetch the corresponding user.
Something like that:
"teams": {
"xxxxxxx": {
"ids": [0: "bKvysPZZCudBKbbjLYV8ZKr1NUo1", 1: XOvysPZZCudBKbbjLYV8ZKr1NUo1]
}
}
But I do not know if it is the best solution. I would like your opinion.
Tks.
I would recommend making a dictionary of IDs where each ID maps with the boolean value of true. I.e.:
"team-users": {
"team1": [
"uid1": true,
"uid2": true,
...
]
}
if you want to get a team that a user is a part of, then use a parallel structure in you database. Add the following node:
"user-teams": {
"uid1": [
"team1": true,
"team2": true,
...
]
}
Reading from this separate node is faster than querying.
I created a flatted data structure. When pushing duplicated data whats the accepted pattern for keeping that data up-to-date. Here the data for the groups info is duplicated into the users-groups and the groups tree.
{
"users": ..
"users-groups": ..
"groups": ..
}
When creating a group for a user two updates takes place:
First: push to /groups/group_key
{
"name": "Test Group",
"image: "/testimage.jpg"
}
Second: push to /users-groups/user_uid/group_key
{
"orderNum: 0,
"info": {
"name": "Test Group",
"image: "/testimage.jpg"
}
}
Should keeping this data in the user-groups up-to-date be a job for the client or should a server handle this?
The data in the groups tree will always be the newest and the changes should propagate down to all the users that are members of that group.
Is there any tutorials or reference material for this problem?
note: i'm using this structure because a user can be a member of multiple groups and I don't think it would be a good idea to make possibly several ref.once's to get the data from the /groups/ directly.
You can use multi path update. Just observe reference with function and update all other informations
db.ref("").update({
'/users/dedd': info,
'/users/cdcd': info2
})
You should not have data saved duplicated. Instead you should save reference to group.
Your data should look like this.
{
"users": {
"userkey1": {
"data": {
"name": "",
"firstname": ""
},
"groups": {
"groupkey1": true // true or orderNum value
}
}
},
"groups": {
"groupkey1": {
"data": {
"name": "Test Group",
"image": "/testimage.jpg",
"other": "data"
},
"users": {
"userkey1": true
}
}
}
}
You can easily check if user is in group by checking if value at any of these positions is true.
users/userkey1/groups/groupkey1 or groups/groupkey1/users/userkey1.
When you create new group you save in under groups/newgroupkey position and you updated groups under users node by only setting newgroupkey to true.
So you do not duplicate your data.
For more information about structuring your data check the following link.
https://firebase.google.com/docs/database/android/structure-data