How to query JSON data from an object in sequelize? - postgresql

I'm new in sequelize so I'd like to ask how to query some specific data from JSON, the JSON in question is inside an onject. Suppose I have this data structure:
{ id: INTEGER, name: json, email: STRING}
{ id: 1, name : { "first": "foo", "last": "bar"}, email: blabla#gmail.com}
And want to retrieve only id and only "last" from all data like this:
{{id: 1, name: {"last": "baz"}, {id: 2, name: {"last": "doe"}}
How can I do this with sequelize guys? I'm really lost. I use postgres as database by the way. Thanks.

You can use attributes option with sequelize.json
const payload = await sequelize.<modelname>.findAll({
attributes: ['id',
[sequelize.json('name.last'), 'last']]
});
It means like:
select id, name->>'last' as last from ...

Related

GraphiQL Mutation: How can I ignore other objects in query variables

Currently having hard time setting up my end points clerk to hasura.
I am absolute new to this platform specially at GraphiQL and just following documentations and youtube video
What I am trying to do is import/insert specific data i neeed only from clerk. Here's the sample query variables:
{
"data": {
"birthday": "",
"created_at": 1654012591514,
"email_addresses": [
{
"email_address": "example#example.org",
"id": "idn_29w83yL7CwVlJXylYLxcslromF1",
"linked_to": [],
"object": "email_address",
"verification": {
"status": "verified",
"strategy": "ticket"
}
}
],
"external_accounts": [],
"external_id": "567772",
"first_name": "Example",
"gender": "",
"id": "user_29w83sxmDNGwOuEthce5gg56FcC",
"last_name": "Example",
"last_sign_in_at": 1654012591514,
"object": "user",
"password_enabled": true,
"phone_numbers": [],
"primary_email_address_id": "idn_29w83yL7CwVlJXylYLxcslromF1",
"primary_phone_number_id": null,
"primary_web3_wallet_id": null,
"private_metadata": {},
"profile_image_url": "https://www.gravatar.com/avatar?d=mp",
"public_metadata": {},
"two_factor_enabled": false,
"unsafe_metadata": {},
"updated_at": 1654012591835,
"username": null,
"web3_wallets": []
},
"object": "event",
"type": "user.created"
}
What I only need to this object is content inside of the "data" is: created_at, first_name, user_id, updated_at, profile_image_url
The GraphiQL Query I did is:
mutation CreateUser(
$created_at: String,
$first_name: String,
$user_id: String,
$updated_at: String,
$profile_image_url: String
)
{
insert_users_one(object:
{
created_at: $created_at,
first_name: $first_name,
user_id: $user_id,
updated_at: $updated_at,
profile_image_url: $profile_image_url,
}) {
created_at
first_name
user_id
updated_at
profile_image_url
}
}
Which throwing error of:
{
"errors": [
{
"extensions": {
"code": "validation-failed",
"path": "$"
},
"message": "unexpected variables in variableValues: object, type, data"
}
]
}
I tried using other method like this:
mutation CreateUser($data: users_insert_input!) {
insert_users_one(object: $data) {
created_at
first_name
user_id
updated_at
profile_image_url
}
}
But it is still having error because of object and type fields
{
"errors": [
{
"extensions": {
"code": "validation-failed",
"path": "$"
},
"message": "unexpected variables in variableValues: object, type"
}
]
}
Here's a sample of GraphQL type:
//is this how you break things down?
type Mutation {
data(
created_at: Int
first_name: String
id: String
updated_at: Int
profile_image_url: String
): Data
}
//this is what i will send in the database, things that I only need
type Verification {
status: String
strategy: String
}
type EmailAddresses {
email_address: String
id: String
object: String
verification: Verification
linked_to: [String]
}
type Data {
birthday: String
created_at: Int
external_id: String
first_name: String
gender: String
id: String
last_name: String
last_sign_in_at: Int
object: String
password_enabled: Boolean
primary_email_address_id: String
primary_phone_number_id: String
primary_web3_wallet_id: String
profile_image_url: String
two_factor_enabled: Boolean
updated_at: Int
username: String
web3_wallets: [String]
phone_numbers: [String]
external_accounts: [String]
email_addresses: [EmailAddresses]
}
type AutogeneratedMainType {
object: String
type: String
data: Data
}
I was expecting based on documents, It will ignore aren't included data.
Visit Github Discussions here
Context about the error
This is error you are receiving is based on this graphql spec - https://spec.graphql.org/June2018/#sec-Input-Objects . More over there is also a different spec for validation against variables here - https://spec.graphql.org/June2018/#sec-All-Variables-Used
TLDR; Using variable which isn’t defined in operation, will result into “unexpected variableValues” error. In your case apart from data , you have type and object as variables in your query variables object which is not defined in operation itself. Remember that query variables is an “object” expecting the variable key-values in it.
Workaround
Cleanest way to do this is to sanitize your object (which you will pass in query variables) by either creating a new object from it and passing data to it or either you remove the unnecessary fields from it which are not defined in operation. You could just delete the properties of that object. Consider yourObject containing data,type and object fields. Then you can do delete yourObject.type and delete yourObject.object. And then pass it.
This workaround is intended for client side code. But there's no exception for graphiQL explorer as that error would be thrown upon undefined variables in operation. If trying via graphiQL explorer, you would manually need to not pass those variables in query variables scope.
Conclusion
This behavior is in compliant with this graphql spec and not with Hasura directly, so we would suggest you to go through those graphql spec links and understand the aspect of it.

How to post a date object in nodejs and mongodb

Following is my schema definition:
var mongoose = require('mongoose');
var Schema = mongoose.Schema;
var StudentSchema = new Schema({
name: String,
family: String,
created: {
type: Date,
default: Date.now}
});
module.exports = mongoose.model('Student', StudentSchema);
How do I have post it? because whatever value I post, it default value, that current time. I tried following two things:
{
"name": "abc",
"family": "xyz",
"created": "2016-12-12"
}
{
"name": "abc",
"family": "xyz",
"created": "1467883104"
}
In both the cases, it stored current time only. Not the one which I am passing.
Your schema defines the field created as Date object. What you are trying to store, however, is a plain string. You have to pass a real Date object instead:
{
name: "abc",
family: "xyz",
created: new Date("2016-12-12")
}

Design of RESTful endpoint for querying based on aggregate data

Let's say we have two resources: Person, Movie.
persons/123
{id: 123, firstName: "John", lastName:"Travolta"}
persons/124
{id: 124, firstName: "Uma", lastName: "Thurman"}
persons/125
{id: 125, firstName: "Bob", lastName: "Saget"}
persons/126
{id: 126, firstName: "Christopher", lastName: "Walken"}
persons/127
{id: 127, firstName: "Steve", lastName: "Buscemi"}
movies/1
{id: 1, name: "Pulp Fiction"}
movies/2
{id:2, name: "Reservoir Dogs"}
Then, to relate the two, we have another resource: Cast Member
GET cast-members?movie.name=Pulp%20Fiction
[
{
id: 502,
movie: {id: 1, name: "Pulp Fiction"}
actor: {id: 123, firstName: "John", lastName:"Travolta"},
character: "Vincent Vega"
},
{
id: 503,
movie: {id: 1, name: "Pulp Fiction"}
actor: {id: 124, firstName: "Uma", lastName: "Thurman"},
character: "Mia Wallace"
},
{
id: 504,
movie: {id: 1, name: "Pulp Fiction"}
actor: {id: 126, firstName: "Christopher", lastName: "Walken"},
character: "Buddy Holly"
},
...
]
If I want to see all of the movies Christopher Walken has been in, I know I can do this:
GET cast-members?actor.id=125
What if I want to see all movies where both Uma Thurman and John Travolta are in the Cast? What does this endpoint look like?
GET cast-members?actor.id=124&actor.id=125
doesn't work.
We return Cast Members where actor.id was either 124 or 125?
[
{
id: 587,
movie: {id: 10, name: "Kill Bill"},
// John's not in this movie
actor: {id: 124, firstName: "Uma", lastName: "Thurman"},
character: "The Bride"
},
{
id: 597,
movie: {id: 11, name: "Saturday Night Fever"},
// Uma's not in this movie
actor: {id: 123, firstName: "John", lastName:"Travolta"},
character: "Tony Manero"
},
...
]
This wouldn't be what we want, because we would have to join the movies on the client side (which isn't desirable since it means we have to page through a lot of data before being able to return a result).
the SQL query would be this:
SELECT Movie
FROM CastMember
WHERE Actor in (124, 125)
GROUP BY Movie
HAVING COUNT(DISTINCT Actor) = 2
Is there a way to translate this query to something that makes RESTful sense?
Perhaps the problem is the 'cast-members' resource - it's not clear that its modelling a real resource rather than some kind of 'synthetic' resource. Not all tables in a relational database are actually resources. ReSTful relationships are generally modeled as links between resources rather than as resources themselves.
The core of your resource breakdown here is that you've got
movie
person
and they're (perhaps) grouped into collections
movies
people
Let's say that you structure your URI space so that you've got
/movie
a collection of movies
/movie/{id}
an individual movie with a given id
/person
a collection of people, possibly not all just actors in movies
/person/{id}
an individual actor with a given id
If you want to find all the movies that a person was in, you search your movies resource based on an 'actor' query. That query could take multiple values, because it makes perfect sense to say that a given movie has more than one actor.
So, if you want to find all the films that persons with ids 1234 and 5678 were in your query should be
GET /movie?actor=1234,5678
Now, you could implement that in a few different ways depending on your use case. Perhaps it would only return a list of movie URIs and you'd have to query each one individually, but that doesn't sound great. Perhaps, on the other hand, it would return a list of all the full movie documents which match (titles, full cast, year, length, synopsis, reviews etc) - that could be a lot of data, so you might add a page parameter...
GET /movie?actor=1234,5678&page=2&pageSize=10
Perhaps you only want some of the details associated with each movie - you could add a parameter for the details which make sense for you....
GET /movie?actor=1234,5678&details=title,id,cast
Note: so far there hasn't been need for a 'person' resource. However, the response document from your movies query will contain links to both individual movie URIs and person URIs...
movies?actor=12345,5678
[
{
movie: {id: 10, uri:"/movies/10", name: "...",
cast: [{id: 12345, uri:"/people/12345", firstName: ... }
{id: 5678, uri:"/people/5678", firstName:...}
{...}
]
}
},
{
movie: {id: 11, uri: "/movies/11", name: "...",
cast: [{id: 12345, uri:"/people/12345", firstName: ... }
{id: 5678, uri:"/people/5678", firstName:...}
{...}
]
}
},
...
]

Cassandra data model to store embedded documents

In mongodb we can able to store embedded documents into a collection.Then, How do we store embedded documents into cassandra??? For this sample JSON representation???
UserProfile = {
name: "user profile",
Dave Jones: {
email: {name: "email", value: "dave#email.com", timestamp: 125555555},
userName: {name: "userName", value: "Dave", timestamp: 125555555}
},
Paul Simon: {
email: {name: "email", value: "paul#email.com", timestamp: 125555555},
phone: {name: "phone", value: "4155551212", timestamp: 125555555},
userName: {name: "userName", value: "Paul", timestamp: 125555555}
}
}
If your document nesting level is not too deep, you can use User Defined Types from C* 2.1.
I personally suggest to rethink your schema into more flat form like:
create table profiles (
name text,
name2 text,
email text,
username text,
ts timestamp,
primary key (name,name2) // compound primary key!
)

Reference field within same schema

Is it possible to reference field within same schema? See my example below. Or am I going about this wrong way?
var UserSchema = new mongoose.Schema ({
username: String,
password: String,
email: String,
foods: [{
name: String,
category: String,
ingredients: // how to reference values in the ingredients array?
}],
ingredients: [{
name: String,
category: String
}]
});
Short answer
This is a core MongoDB design decision: MongoDB relationships: embed or reference?
Storing references to objects, rather than independent copies of them, as you would do in a relational database is possible in MongoDB and often done, it just results in more and more complex queries when you need to look them up.
Long answer
If the goal is just to keep the definitions of ingredient schemas consistent, you can define a schema and use it twice. The ingredients will be stored as independent copies, e.g.
[{ username: 'bob',
ingredients: [ { name: 'Carrot', category: 'Vegetable' } , ...],
foods: [ { name: 'Salad', category: 'Lunch', ingredients: [ { name: 'Carrot', category: 'Vegetable'}, ...]}]
}, ...]
var IngredientSchema = new mongoose.Schema({
name: String,
category: String,
});
var UserSchema = new mongoose.Schema ({
username: String,
password: String,
email: String,
foods: [{
name: String,
category: String,
ingredients: [IngredientSchema] // brackets indicates it's an array,
}],
ingredients: [IngredientSchema]
});
Alternatively you can reference ingredients by objectId:
var UserSchema = new mongoose.Schema ({
username: String,
password: String,
email: String,
foods: [{
name: String,
category: String,
ingredients: [mongoose.Schema.Types.ObjectId] // IDs reference individual ingredients,
}],
ingredients: [IngredientSchema]
});
By defining IngredientSchema explicitly, each ingredient object gets its own ObjectId when it is declared. The upside to storing IDs of ingredients (rather than copies of ingredient objects) is more concise and consistent storage. The downside is there will be many more and more complex queries.
[{ username: 'bob',
ingredients: [ { _id: ObjectId('a298d9ef898afc98ddf'), name: 'Carrot', category: 'Vegetable' } , ...],
foods: [ { name: 'Salad', category: 'Lunch', ingredients: [ {$oid: 'a298d9ef898afc98ddf'}, ]}]
}, ...]
A better approach if you want to store references to Ingredients, may be to store Ingredients as its own first class collection. You'll still have many separate queries when you want to look up foods by ingredient, or ingredients by food, but the queries will be simpler.
var UserSchema = new mongoose.Schema ({
username: String,
password: String,
email: String,
foods: [{
name: String,
category: String,
ingredients: [mongoose.Schema.Types.ObjectId] // IDs reference individual ingredients,
}],
ingredients: [mongoose.Schema.Types.ObjectId]
});
if the goal is store normalized references to ingredients and search foods based on them, to quote another [SO post][1], "this is one of those cases where relational databases really shine"
See this SO post for querying subdocuments by Id:
Reading categories and number of articles in a single query
As one respondent notes, "this is one of those cases where relational databases really shine"