Mongoose refPath one path multi model populate - performance

Used refPath here documentation: https://mongoosejs.com/docs/populate.html#dynamic-ref
const match = { $or: [{ build: variable }, { country: variable }], isDeleted: undefined };
const populate = [
{ path: `reviewer`, model: 'Build', select: { _id: 1, username: 1, } },
{ path: `reviewer`, model: 'Country', select: { _id: 1, username: 1 } },
];
const buildPopulate = await this.reviewsModel.find(match).select(select).populate(populate[0]).lean().exec();
const countryPopulate = await this.reviewsModel.find(match).select(select).populate(populate[1]).lean().exec();
return { buildPopulate, countryPopulate };
When i was try to populate with just one query i cant get populate[0] already get reviewer null.
I have find this solution but i think is not healthy solution. Anyone have idea ??

Related

Displaying the password on a filtered request

Strapi Version: 4.4.5
Operating System: linux
Database: sqlite
Node Version: 16.17.0
NPM Version:
Yarn Version: 1.22.19
Hello,
I'm just trying to get all the information from my "Channel" table, namely the product_id and the "users" concerned in the channel. I simply overload my find method like this:
module.exports = createCoreController("api::channel.channel", ({ strapi }) => ({
async find(ctx) {
const { user } = ctx.state:
const entity = await strapi.service("api::channel.channel").find({
filters: {
users: {
id: {
$in: user.id,
},
},
},
populate: ["users"]
});
const sanitizedEntity = await this.sanitizeOutput(entity, ctx);
return this.transformResponse(sanitizedEntity);
},
}));
And for some reason, I get all the user information and especially the hash of the passwords.
So I try to do a select on my populate like this, but it doesn't work :
module.exports = createCoreController("api::channel.channel", ({ strapi }) => ({
async find(ctx) {
const { user } = ctx.state;
const entity = await strapi.service("api::channel.channel").find({
filters: {
users: {
id: {
$in: user.id,
},
},
},
populate: {
users: {
select: ["id"]
}
}
});
const sanitizedEntity = await this.sanitizeOutput(entity, ctx);
return this.transformResponse(sanitizedEntity);
},
}));
Does anyone have a solution to my problem?
It is not select, you would use fields
Strapi Population
const qs = require('qs');
const query = qs.stringify({
fields: ['title', 'body'],
}, {
encodeValuesOnly: true, // prettify URL
});
So in your case, fields in combination with populate.
populate: {
users: {
fields: ["id"]
}
}

todo list optimistic subscription updates with Apollo GraphQl

I am trying to get an optimistic response when I add a task to my todo list:
ADD_TASK and GET_TASK from query.ts
export const GET_TASKS = gql`
subscription {
queryTask {
id
title
completed
user {
username
}
}
}
`;
export const ADD_TASK = gql`
mutation addTask($task: AddTaskInput!) {
addTask(input: [$task]) {
task {
id
title
completed
}
}
}
`;
addTask() function
const newId = Math.round(Math.random() * -1000000);
await addTask({
variables: {
task: {
title: text,
completed: false,
user: { username: user?.email },
},
},
optimisticResponse: {
__typename: "Mutation",
addTask: {
__typename: "AddTaskPayload",
task: {
__typename: "Task",
id: newId,
title: text,
completed: false,
user: {
__typename: "User",
username: user?.email,
},
},
},
},
update(cache, { data: addTask }: any) {
const queryTask: any = cache.readQuery({
query: GET_TASKS,
});
cache.writeQuery({
query: GET_TASKS,
data: {
queryTask: [...queryTask.queryTask, addTask.addTask.task],
},
});
},
});
UPDATE
So, I got it working normally, now I just need to get it working with:
1.) Subscriptions
2.) The ID problem... it generates a random ID here instead of knowing what it should be (any suggestions)?
I am using my repository with Dgraph here.
(This does not include the optimistic version)
Any suggestions?
J

Graphql multiple arguments in field

I'm using GraphQL.
I'm able to pass one argument in a field. But I would like to know how to pass multiple arguments to a field.
This is my code:
GraphlQL Object type: Price availability
const priceAvailability = new GraphQLObjectType({
name: "priceAvailability",
description: "Check price and availability of article",
fields: () => ({
articleID: {
type: GraphQLString
},
priceType:{
type:GraphQLString
},
stockAvailability: {
type: StockAvailabilityType,
resolve(parentValue, args) {
// stuff to get the price and availability
return (data = getStockAvailability.getStockAvailability(
parentValue.isbn, parentValue.omgeving
));
}
}
})
});
The root query
const RootQuery = new GraphQLObjectType({
name: "RootQuery",
fields: () => ({
price: {
type: new GraphQLList(priceAvailability),
args: [{
articleID: {
type: new GraphQLList(GraphQLString),
description:
'List with articles. Example: ["artid1","artid2"]'
},
priceType: {
type: new GraphQLList(GraphQLString) ,
description:
'PriceType. Example: "SalePrice","CurrentPrice"'
}]
},
resolve: function(_, { articleID , priceType}) {
var data = [];
// code to return data here
return data;
}
}
})
});
Schema
module.exports = new GraphQLSchema({
query: RootQuery
});
This is the query I use in GraphiQL to test:
{
query: price(articleID:"ART03903", priceType:"SalePrice" ){
stockAvailability {
QuantityAvailable24hrs
QuantityAvailable48hrs
}
}
}
I can get the articleID via parentValue.articleID, but I have issues with getting parentValue.priceType.
Also GraphiQL tells me that priceType does not exists:
Unknown argument “priceType”. On field “price” of type “RootQuery”
args for a field takes an object instead of an array. Try:
args: {
articleID: {
type: new GraphQLList(GraphQLString),
description: 'List with articles. Example: ["artid1","artid2"]'
},
priceType: {
type: new GraphQLList(GraphQLString) ,
description: 'PriceType. Example: "SalePrice","CurrentPrice"'
},
}

Normalize linked ids

I have a weird set of data here.
const data = {
profiles: [
{ name: 'Joe', photos: [1, 2, 3] },
{ name: 'Ryan', photos: [2] },
{ name: 'Bob', photos: null }
],
linked: {
photos: [
{ id: 1, url: 'http://blah' },
{ id: 2, url: 'blah' },
{ id: 3, url: 'asdf' }
]
}
}
I get all the profiles like this:
const { entities } = normalize(data, {
profiles: [ Profile ]
});
But I want to replace the photos id array with the entries from linked.photos, is this possible? Or does it require post processing? I am currently doing custom post processing.
I'm not sure that normalizr is the best aproach for your task, but something like this will work
const photoSchema = new schema.Entity('photos', {});
const normalized = normalize(data.linked.photos, [photoSchema]);
const profileRawSchema = new schema.Entity('profiles', {}, {idAttribute: 'name'})
const profileSchema = new schema.Entity('profiles', {
photos: [photoSchema]
}, {idAttribute: 'name'});
const normalizedProfiles = normalize(
data.profiles,
[profileRawSchema]
);
normalized.entities.profiles = normalizedProfiles.entities.profiles;
// here is what you want
const desiredResult = denormalize(normalizedProfiles.result, [profileSchema], normalized.entities);
Docs for denormalize

Issue in querying graphQL relay calls (.then is not a function)

I have a graphql server running which I am using for query one of the object that gets instantiated when server starts (kind of in-memory db). Here company object is created every time schema is loaded or say server is started which I am using in QueryType object to resolve.
Here is the graphQL Schema
const {
GraphQLSchema,
GraphQLObjectType,
GraphQLString,
GraphQLInt,
GraphQLList
} = require('graphql');
const {
connectionDefinitions,
connectionArgs,
connectionFromArray,
connectionFromPromisedArray
} = require('graphql-relay');
//**************************** In-Memory Data ********************************//
var company = {
id:'123456',
customFieldDefinitions:[
{
name: 'cfm1',
id: '123'
},
{
name: 'cfm2',
id: '1234'
}
]
};
//**************************** In-Memory Code Ends *********************************//
const CustomFieldDefinitionType = new GraphQLObjectType({
name: 'Common_CustomFieldDefinitionsConnection',
fields: {
id: {
type: GraphQLString,
resolve: (cfd) => cfd.id
},
name: {
type: GraphQLString,
resolve: (cfd) => cfd.name
}
}
});
const { connectionType: CustomFieldDefinitionConnection } =
connectionDefinitions({
name: 'Common_CustomFieldDefinition',
nodeType: CustomFieldDefinitionType
});
const CompanyType = new GraphQLObjectType({
name: 'Company',
fields: {
id: {
type: GraphQLString,
resolve: (obj) => obj.id
},
customFieldDefinitions: {
type: CustomFieldDefinitionConnection,
description: 'A list of Custom Fields',
args: connectionArgs,
resolve: (obj, args) => connectionFromPromisedArray(obj.customFieldDefinitions, args)
}
}
});
const QueryType = new GraphQLObjectType({
name: 'Query',
fields: {
company: {
args: {
id: { type: GraphQLString },
},
type: CompanyType,
resolve: (_, args) => company
}
}
});
const mySchema = new GraphQLSchema({
query: QueryType
});
module.exports = mySchema;
Now when I try to query as below on graphiQL editor
query{
company{
customFieldDefinitions {
edges {
node {
id
}
}
}
}
}
I get error as below.
{
"data": {
"company": {
"customFieldDefinitions": null
}
},
"errors": [
{
"message": "dataPromise.then is not a function",
"locations": [
{
"line": 3,
"column": 5
}
],
"path": [
"company",
"customFieldDefinitions"
]
}
]
}
How can I identify the problem?
It looks like the error is with this line:
resolve: (obj, args) => connectionFromPromisedArray(obj.customFieldDefinitions, args)
The problem is that the connectionFromPromisedArray function imported from graphql-relay expects a promise that returns an array and obj.customFieldDefinitions is a normal array. Just to trace it back, obj is the parent element of that resolver which in this case is what you return from the company resolver on the Query type.
To fix it, either change connectionFromPromisedArray to connectionFromArray or change your company object to this:
var company = {
id:'123456',
customFieldDefinitions: Promise.resolve([
{
name: 'cfm1',
id: '123'
},
{
name: 'cfm2',
id: '1234'
}
])
};

Resources