Having trouble converting schema from Normalizr v2 to v3 - javascript

I just updated to normalizr version 3.1.x so I can utilize the denormalization. Though they've significantly changed their API. I'm having trouble transferring my schemas over.
import { normalize, Schema, arrayOf, valuesOf } from 'normalizr';
const usersSchema = new Schema('users')
const photosSchema = new Schema('photos')
const phonesSchema = new Schema('phones')
photosSchema.define({
users: arrayOf(usersSchema)
})
phonesSchema.define({
users: arrayOf(usersSchema)
})
usersSchema.define({
photos: valuesOf(photosSchema),
phones: valuesOf(phonesSchema)
})
That was my existing schema for users. I was also using the redux-normalizr middleware inside my redux action, so I connected the schema to my action like this:
import { usersSchema } from '../normalizrSchemas/usersSchemas.js'
import { arrayOf } from 'normalizr'
export function getUsers(data) {
return {
type: 'GET_USERS',
payload: data,
meta: {
schema : arrayOf(usersSchema)
}
}
}
This was my first attempt to convert the schema over. It doesn't seem you can call schema.Array the same way you could using arrayOf, so I thought I needed to move the array call into the schema.
import { schema } from 'normalizr';
const photos = new schema.Entity('photos')
const phones = new schema.Entity('phones')
const user = new schema.Entity('user', {
photos: [photos],
phones: [phones]
})
const users= new schema.Array('users', user)
export { users }
the action is the same, but i've removed wrapping the schema in arrayOf. All of the users data is just getting dumped into results without any normalization. The data is a list of user object, and each object contains an id, which normalizr should pick up. I'm struggling to figure out how to get normalizr the identify that it's an array of object I think.

schema.Array does not accept a key string name (docs). The first argument should be the schema definition. So instead of
const users= new schema.Array('users', user)
You should use:
const users = new schema.Array(user)
Or, you could just use the shorthand for an array of a single entity type:
const users = [ user ];

Related

Creating Schema in Node/MongoDb

So, I am just starting with Node/Mongo db and typescript, and I am kind of stuck in creating a Schema for this nested JSON Database. I have started something and, I would like to know if I am on the right track. So please if anyone would help me it would be great. Thanks in Advance
Data
[{
"a_class":[
{
"brand":"A-class",
"id":"1",
"year":"2015"
"price":"12665"
...
"engine_spec":{
...
}
...
}]
}
]
Interfaces
import { Document } from 'mongoose';
export default interface ICars extends Document {
a_class: BrandList[],
}
interface BrandList {
brand: string;
id:number;
year:number;
main_image: string;
price:number;
transmission:string;
fuel_type:string;
seating_capacity:number;
engine:number;
engine_specs:Specs;
volume_weights:Volume;
performance: Performance
images_interior: Interior
images_exterior: Exterior
}
interface Specs {
power:number;
power_per_litre:number;
torque:number;
fuel_system:number
}
interface Volume {
max_weights:number;
fuel_tank:number
}
interface Performance {
acceleration:number;
maximum_speed:number;
fuel_urban:number;
fuel_extra_urban:number
fuel_combined:number
}
interface Interior {
image_one:string;
image_two:string;
image_three:string;
image_four:string;
}
interface Exterior {
image_one:string;
image_two:string;
image_three:string;
image_four:string;
}
Schema
import mongoose, { Schema } from 'mongoose';
import ICars from '../interfaces/cars'
const CarsSchema: Schema = new Schema({
a_class:Array,
brand: String,
year:Number,
})
export default mongoose.model<ICars>('Cars', CarsSchema);
Get Route, So when I try to get all the data through postman, it is not allowing me, it is saying that the route is not being found 404. I have imported it to the server.js import carsRouter from './routes/cars'; router.use('./cars',carsRouter ), I don't know where the error could be
import express from 'express'
import Cars from '../models/cars'
const router = express();
router.get('/cars', (req:any, res:any )=>{
Cars.find()
.then(car=> res.json(car))
.catch(err => res.status(400).json(`Error: ${err}`))
})
export=router
According to mongoose document, we should avoid extending mongoose Document.
This approach works, but we recommend your document interface not
extend Document. Using extends Document makes it difficult for
Mongoose to infer which properties are present on query filters, lean
documents, and other cases.
We recommend your document interface contain the properties defined in
your schema and line up with what your documents look like in MongoDB.
Although you can add instance methods to your document interface, we
do not recommend doing so.
For more information, please reference: https://mongoosejs.com/docs/typescript.html#using-extends-document
And It seems that we can use mongoose sub documents for this requirement. For more information regarding the sub documents, please reference: https://mongoosejs.com/docs/subdocs.html#subdocuments
So in this case, we can rephrase your code a little bit:
Interfaces:
export default interface ICars {
a_class: BrandList[],
}
// The other interfaces can be kept
Schema:
const Exterior = new Schema({
// own fields
});
const Interior = new Schema({
// own fields
});
const Performance = new Schema({
// own fields
});
const Volume = new Schema({
// own fields
});
const SpecsSchema = new Schema({
// own fields
});
const BrandListSchema = new Schema({
// other fields
engine_specs: [SpecsSchema],
volume_weights: [VolumeSchema],
performance: [PerformanceSchema],
images_interior: [InteriorSchema],
images_exterior: [ExteriorSchema],
});
const CarsSchema: Schema = new Schema({
a_class: [BrandListSchema],
});

How to use arrayUnion with AngularFirestore?

I have a basic database that essentially stores an array of product id's underneath a user. The user can select products to add to the array so it makes sense to use 'arrayUnion' so I avoid reading and re-writing the array constantly, however, I keep getting the error *"Property 'firestore' does not exist on type 'FirebaseNamespace'."
I've followed the documentation found at: https://firebase.google.com/docs/firestore/manage-data/add-data#update_elements_in_an_array but I fear I'm still using it incorrectly.
My code for updating the array is:
addToPad(notepadName: string){
const updateRef = this.db.collection('users').doc(this.activeUserID).collection('notepads').doc(notepadName);
updateRef.update({
products: firebase.firestore.FieldValue.arrayUnion(this.productId)
});
}
First you need to import firestore:
import { firestore } from 'firebase/app';
Then you will be able to use arrayUnion:
addToPad(notepadName: string){
const updateRef = this.db.collection('users').doc(this.activeUserID).collection('notepads').doc(notepadName);
updateRef.update({
products: firestore.FieldValue.arrayUnion(this.productId)
});
}
import { arrayUnion } from '#angular/fire/firestore'
const path = `ai/${videoId}/panel-operation/${id}`
const myDoc: AngularFirestoreDocument<any> = this.afs.doc<any>(path)
const promise: Promise<void> = myDoc.update({ auxPanelSelections: arrayUnion({auxPanel: 'clip', operation: 'replace'}) }).catch((err: any) => {
console.error(`oopsie - ${err.message}`)
return null
})
auxPanelSelections is an array within the myDoc document
Note that the above code also works perfectly fine with arrayRemove
I cannot find the #angular/fire docs for arrayUnion but the generic docs are here

Add custom GraphQL resolvers and types into Prisma/Nexus schema

Using: TypeScript, Prisma, MySQL, GraphQLServer, ApolloClient, building schema this way:
const schema = makePrismaSchema({
// Provide all the GraphQL types we've implemented
types: [Query, Mutation, User, Post],...
And then:
const server = new GraphQLServer({
schema,
context: { prisma }
});
How to combine that with custom resolvers and types unrelated to the SQL?
(I would like to call some REST endpoint by the GQL as well)
While nexus was created to be used alongside prisma, it's really just a schema builder. You could easily use it to create a schema without even utilizing Prisma. For example:
export const User = prismaObjectType({
name: 'User',
definition(t) {
t.list.field('comments', {
type: 'Comment',
resolve(root, args, ctx) {
return getComments();
},
});
},
})
export const Comment = prismaObjectType({
name: 'Comment',
definition(t) {
t.string('body');
},
})
Here getComments can return an array of comment objects, or a Promise that resolves to one. For example, if you're calling some other API, you'll normally return a Promise with the results of the call. As shown above, the resolver exposes the parent value, the field's arguments and a context object -- you can use any of this information in determining how to resolve a particular field.

Mocking GraphQL, MockList genertes only two items in the array

I am trying to generate a list of 10 items in my GraphQL mock server like this:
import { makeExecutableSchema, addMockFunctionsToSchema, MockList } from 'graphql-tools';
import casual from 'casual';
import typeDefs from './schema.graphql';
export const schema = makeExecutableSchema({ typeDefs });
const mocks = {
File: () => ({
path: casual.random_element([
'/assets/images/cars/1.JPG',
'/assets/images/cars/2.JPG',
'/assets/images/cars/3.JPG',
'/assets/images/cars/4.JPG',
'/assets/images/cars/5.JPG',
'/assets/images/cars/6.JPG',
'/assets/images/cars/7.JPG',
]),
}),
UsedCar: () =>
new MockList(10, () => ({
price: casual.integer(10000, 99999999),
year: casual.integer(1990, 2017),
})),
};
// This function call adds the mocks to your schema!
addMockFunctionsToSchema({ schema, mocks });
But I always get two used cars I don't know why.
Can anyone help?
Regards,
Mostafa
In your code, you are defining a mock resolver for your UsedCar type. You didn't post your typeDefs or resolvers, but I'm guessing your type definition for UsedCar includes the two fields (price and year)... not a whole array of objects with those two fields. However, that is what you are telling the mock function you have.
If you have a query that fetches an array of UsedCar types, in order to get 10 mocked objects of that type, you will have to mock both the query and the type. So, assuming you have a query like getUsedCars, what you really want is:
mocks: {
Query: () => ({
getUsedCars: () => new MockList(10)
}),
UsedCar: () => ({
price: casual.integer(10000, 99999999),
year: casual.integer(1990, 2017),
})
}
Edit: If you only mock the type, anywhere in the schema that resolves to an array of that type will return two mocked objects by default, which is why you were seeing two instead of ten.

Updating nested objects firebase

From the Firebase note:
Given a single key path like alanisawesome, updateChildren() only updates data at the first child level, and any data passed in beyond the first child level is a treated as a setValue() operation. Multi-path behavior allows longer paths (like alanisawesome/nickname) to be used without overwriting data. This is why the first example differs from the second example.
I am trying to use a single function createOrUpdateData(object) in my code. In case of update, it updates first level children properly, but if I have nested object passed, then it deletes all other properties of that nested object.
Here's the code:
function saveUserDetails(email,object){
var hashedEmail = Utilities.getHashCode(email);
var userRef = ref.child(hashedEmail);
return $q(function(resolve,reject){
return userRef.update(object, function(error){
if(error){
reject(error);
}else{
resolve("Updated successfully!");
}
});
});
}
So if I pass:
{
name: 'Rohan Dalvi',
externalLinks: {
website: 'mywebsite'
}
}
Then it will delete other properties inside externalLinks object. Is there a cleaner and simpler way of avoiding this?
In short, how do I make sure nested objects are only updated and that data is not deleted.
You can use multi-path updates.
var userRef = ref.child(hashedEmail);
var updateObject = {
name: 'Rohan Dalvi',
"externalLinks/website": 'mywebsite'
};
userRef.update(updateObject);
By using the "externalLinks/website" syntax in the object literal it will treat the nested path as an update and not a set for the nested object. This keeps nested data from being deleted.
This question provides a more recent solution that works with cloud firestore.
Rather than using "/", one may use "." instead:
var userRef = ref.child(hashedEmail);
var updateObject = {
name: 'Rohan Dalvi',
"externalLinks.website": 'mywebsite'
};
userRef.update(updateObject);
To update nested object/map/dictionary in firebase database, you can use Firestore.Encoder to class/struct that is Codable.
Here is a Swift code example:
Models:
import FirebaseFirestore
import FirebaseFirestoreSwift
// UserDetails Model
class UserDetailsModel: Codable {
let name: String,
externalLinks: ExternalLinkModel
}
// UserDetails Model
class ExternalLinkModel: Codable {
let website: String
}
Calling Firebase:
import FirebaseFirestore
import FirebaseFirestoreSwift
let firestoreEncoder = Firestore.Encoder()
let fields: [String: Any] = [
// using firestore encoder to convert object to firebase map
"externalLinks": try! firestoreEncoder.encode(externalLinkModel)
]
db.collection(path)
.document(userId)
.updateData(fields, completion: { error in
...
})

Categories

Resources