Algolia filters on array property not working as expected - filter

I have an index on algolia having users like this
UserA:
{
createdAt: 1675364400000,
email: "abc#gmail.com",
products: [
{
productId: 'product1',
dateAdded: 1675364400000,
dateUpdated: 1675364400000,
status: 'active'
},
{
productId: 'product2',
dateAdded: 1675364400000,
dateUpdated: 1675364400000,
status: 'pending'
},
]
}
UserB:
{
createdAt: 1675364400000,
email: "abc1#gmail.com",
products: [
{
productId: 'product4',
dateAdded: 1675364400000,
dateUpdated: 1675364400000,
status: 'active'
},
{
productId: 'product5',
dateAdded: 1675364400000,
dateUpdated: 1675364400000,
status: 'pending'
},
]
}
Need to apply filter on algolia to get all the users who has product2 with pending status. I'm getting both UserA (because it has product2 pending) and UserB (because it has product with pending status).
I added products.status and products.productId in attributesForFaceting and used the following in filters products.productId:product2 AND products.status:pending. Its getting all the users having product2 and any products with status pending

Changing the structure of the index on algolia helped me to resolve this issue. There are multiple ways to structure the index like mentioned in this but with this approach, can have redundant data and more requests to algolia if we need to update the other fields like createdAt in my case. Here is the structure I used to avoid all these overheads.
{
createdAt: 1675364400000,
email: "abc#gmail.com",
"product1": {
productId: 'product1',
dateAdded: 1675364400000,
dateUpdated: 1675364400000,
status: 'active'
},
"product2": {
productId: 'product2',
dateAdded: 1675364400000,
dateUpdated: 1675364400000,
status: 'pending'
}
}
And in attributesForFaceting added product1.status, product2.status, and the same for all our products. In this way, if we need to update the createdAt on algolia, we must change just one object with no redundant data.
We have a limited number of products that will not change very often. This might have some issues with attributesForFaceting if we have many products and change very often.
I would love to hear suggestions for improvement.

Related

GraphQL: relationships in not normalizable

I am new to GraphQL not sure what I am doing wrong. Any help will be appreciated. I have included my GraphQL schema, data and query here. I am getting exception in query "Value to set in Organization.relationships in not normalizable: Value to set in Relationships.customers in not normalizable: should be an object or null or undefined".
My Schema:
type Query{
searchForOrganization: [Organization!]!
}
type Data{
id: ID
type: String
}
type Group{
data:[Data]
}
type User{
data:[Data]
}
type Customer{
data:[Data]
}
type Relationships{
groups: Group
users: User
customers: Customer
}
type Attributes{
name: String!
description: String
authenticationUrl: String
}
type Organization{
id: ID!
type: String!
attributes: Attributes!
relationships: Relationships!
}
Mock Data:
const mocks = {
Query: () => ({
searchForOrganization: () => [...new Array(9)],
}),
Organization: () => (
{
type: () => "organization",
id: () =>"Test002",
attributes: ()=>{
return{
authenticationUrl: "XXXX",
description: "Test Company",
"name": "Test Company"
};
},
relationships: () => {
return{
customers: () => {
return{
data: [{type: "customer", id: "Test002_Root_customers"},
{type: "customer", id: "Test003_Root_customers"}
]
};},
groups: () => {
return{
data: [{type: "group", id: "Test003_Root_groups"},
{type: "group", id: "Test002_Root_groups"}]
};},
users: () => {
return{
data: [{type: "user", id: "Test003_Root_users"},
{type: "user", id: "Test002_Root_users"}]
};}
};
}
}
),
};
My Query:
query SearchForOrganization {
searchForOrganization {
id
type
attributes {
name
description
authenticationUrl
}
relationships {
groups {
data {
id
type
}
}
users {
data {
id
type
}
}
customers {
data {
id
type
}
}
}
}
}
My Result:
{
"errors": [
{
"message": "Value to set in Organization.relationships in not normalizable: Value to set in Relationships.customers in not normalizable: should be an object or null or undefined. Received () => {\r\n return{\r\n data: [{type: \"customer\", id: \"Test002_Root_customers\"},\r\n {type: \"customer\", id: \"Test003_Root_customers\"}\r\n ]\r\n };}",
"locations": [
{
"line": 10,
"column": 5
}
],
"path": [
"searchForOrganization",
0,
"relationships"
],
"extensions": {
"code": "INTERNAL_SERVER_ERROR",
"exception": {
"stacktrace": [
"Error: Value to set in Organization.relationships in not normalizable: Value to set in Relationships.customers in not normalizable: should be an object or null or undefined. Received () => {\r",
" return{\r",
" data: [{type: \"customer\", id: \"Test002_Root_customers\"},\r",
" {type: \"customer\", id: \"Test003_Root_customers\"}\r",
" ]\r",
" };}",
Change in schema solved the issue
type TypeAndID{
id: ID
type: String
}
type DataGroup{
data:[TypeAndID]
}
type OrgRelationships{
groups: DataGroup
users: DataGroup
customers: DataGroup
}
type Attributes{
name: String!
description: String
authenticationUrl: String
}
type Organization{
id: ID!
type: String!
attributes: Attributes!
relationships: OrgRelationships!
}
type Data{
data: [Organization!]!
}
type Query{
getOrganizations: Data
}

Yup validation rules issues

Just trying to get a handle on Yup and unfortunately I can't seem to find any examples that point to validating a nested object and a nested array (of objects) within another object.
I have something like this:
"books": [{
"info": {
"dateReleased": null,
"timeReleased": null
},
"reviewers": [
{
"company": "",
"name": ""
}
]
}]
I just have no idea what the required Yup validation syntacx is for info and reviewers as all I want to validate is that the values are not null and are required.
I'vetried this but no validation is firing:
Yup.object().shape({
books: Yup.array(
info: Yup.object({
dateReleased: Yup.date().required('Rquired')
timeReleased: Yup.date().required('Required')
})
reviewers: Yup.array(
Yup.object({
company: Yup.string().required('Required')
name: Yup.string().required('Required')
})
)
)
})
With the above, I'm not getting any console errors but none of my validation rules for info and reviewers are firing.
Yup Validation
const value = {
books: [
{
info: {
dateReleased: null,
timeReleased: null,
},
reviewers: [
{
company: "",
name: "",
},
],
},
],
};
const schema = yup.object().shape({
books: yup.array(
yup.object().shape({
info: yup.object().shape({
dateReleased: yup.date().required('Required'),
timeReleased: yup.date().required('Required')
}),
reviewer: yup.array(
yup.object().shape({
company: yup.string().required('Required'),
name: yup.string().required('Required')
})
)
})
),
});
schema.validate(value).catch(err => {
console.log(err.name); // ValidationError
console.log(err.errors); // [books[0].info.timeReleased must be a `date` type, but the final value was: `Invalid Date`.]
});

How to use multiple relations in Laravel

Can some one tell me how to use multiple relations in Laravel
Im try explain the situation
Im have 3 tables in database as like users, orders and order products
Each of these tables is linked by a foreign key.
Im have response like this
address: "test"
birthday: "01-01-2020"
created_at: null
email: "admin#admin.com"
email_verified_at: null
id: 1
name: "Admin"
orders: [,…]
0: {id: 73, user_id: 1, orderNumber: "2180673", total: "350", status: "1", delivery: "1", comment: null,…}
comment: null
created_at: "2020-05-13T20:27:28.000000Z"
delivery: "1"
id: 73
orderNumber: "2180673"
status: "1"
total: "350"
updated_at: "2020-05-13T20:27:28.000000Z"
user_id: 1
phone: "+380991111111"
role: "admin"
surname: "Admin"
uniqueId: null
updated_at: null
Is it possible to get response like this
address: "test"
birthday: "01-01-2020"
created_at: null
email: "admin#admin.com"
email_verified_at: null
id: 1
name: "Admin"
orders: [,…]
0: {id: 73, user_id: 1, orderNumber: "2180673", total: "350", status: "1", delivery: "1", comment: null,…}
comment: null
created_at: "2020-05-13T20:27:28.000000Z"
delivery: "1"
id: 73
orderNumber: "2180673"
order_products: [{id: 3, order_id: 73, product_id: 1, quantity: "1", name: "Test", price: "250",…},…]
0: {id: 3, order_id: 73, product_id: 1, quantity: "1", name: "Test", price: "250",…}
1: {id: 4, order_id: 73, product_id: 2, quantity: "1", name: "Test2", price: "100",…}
status: "1"
total: "350"
updated_at: "2020-05-13T20:27:28.000000Z"
user_id: 1
phone: "+380991111111"
role: "admin"
surname: "Admin"
uniqueId: null
updated_at: null
This is my code in User model file
public function orders()
{
return $this->hasMany('App\Order', 'user_id', 'id');
}
This is my code in Order model file
public function user()
{
return $this->belongsTo('App\User', 'user_id', 'id');
}
public function orderProducts()
{
return $this->hasMany('App\OrderProduct', 'order_id', 'id');
}
This is my code in OrderProduct model file
public function order()
{
return $this->belongsTo('App\Order', 'order_id', 'id');
}
public function product()
{
return $this->belongsTo('App\Product', 'product_id', 'id');
}
If someone have info about this it will be so great
You can eager load the relations but the response will be slightly different from what your're expecting. As far your question goes, try eager load the table like -
$userOrderProducts = App\User::with(['orders', 'orders.orderProducts'])->select('users.*')->get();
ddd($userOrderProducts);
This way you will get collection of users with collection of orders inside it. Ordered products will not be inside the user collection. Instead this will be inside the order collection. If I to show you how the response may look -
user [
...,
order: [
...,
orderProducts: [
...
]
],
]
Know more about eager loading here - Laravel Eager Loading
If you want for every user's order products contained in every order, you can use:
$users = User::with(['orders', 'orders.orderProducts', 'orders.orderProducts.product'])->get();
foreach($users as $user){
foreach($user->orders as $order){
foreach($order->orderProducts as $orderProduct){
echo $orderProduct->product->name;
}
}
}
If you want all products, that had user ordered (without looking on specific order), you can set "Through" relationship. More here: Laravel Docs

GraphQL + Sequalize + existing database - "message": "parent.getPages is not a function" for one model not the other

GraphQL Query
Morning all,
I have a nice setup GraphQL -> Sequalize -> Existing DB (generated by a Laravel application). I've built this schema out:
type App {
id: ID!
userId: ID
user: User
pages: [Page]
experiments: [Experiment]
uri: String!
createdAt: String!
updatedAt: String!
}
type Page {
id: ID!
userId: ID
user: User
appId: ID!
app: App!
uri: String!
createdAt: String!
updatedAt: String!
}
type Experiment {
id: ID!
title: String!
appId: ID!
app: App!
createdAt: String!
updatedAt: String!
}
Based on the existing data. Querying an apps experiments works just great:
query {
app(id: 6) {
id
title
experiments {
id
}
}
}
{
"data": {
"app": {
"id": "6",
"title": "C-Map Embark: Boating",
"experiments": [
{
"id": "1"
}
]
}
}
}
But querying pages I get this:
query {
app(id: 6) {
id
title
pages {
id
}
}
}
{
"errors": [
{
"message": "parent.getPages is not a function",
"locations": [
{
"line": 5,
"column": 5
}
],
"path": [
"app",
"pages"
],
"extensions": {
"code": "INTERNAL_SERVER_ERROR",
"exception": {
"stacktrace": [
"TypeError: parent.getPages is not a function",
...
The db columns are the same, as are the resolvers:
/* jshint indent: 2 */
module.exports = function(sequelize, DataTypes) {
const Page = sequelize.define(
"page",
{
id: {
type: DataTypes.INTEGER(10).UNSIGNED,
allowNull: false,
primaryKey: true,
autoIncrement: true
},
...
createdAt: {
type: DataTypes.DATE,
allowNull: true
},
updatedAt: {
type: DataTypes.DATE,
allowNull: true
}
},
{
tableName: "pages",
underscored: true
}
);
Page.associate = models => {
Page.belongsTo(models.app);
};
return Page;
};
/* jshint indent: 2 */
module.exports = function(sequelize, DataTypes) {
const Experiment = sequelize.define(
"experiment",
{
id: {
type: DataTypes.INTEGER(10).UNSIGNED,
allowNull: false,
primaryKey: true,
autoIncrement: true
},
...
createdAt: {
type: DataTypes.DATE,
allowNull: true
},
updatedAt: {
type: DataTypes.DATE,
allowNull: true
}
},
{
tableName: "experiments",
underscored: true
}
);
Experiment.associate = models => {
Experiment.belongsTo(models.app);
};
return Experiment;
};
Have you come across this before?

Mongoosastic indexes the wrong fields

I have set up mongoosastic to index my documents to elastic search. The trouble is, despite the schema set, all fields are indexed.
My Schema:
id: { type: String, index: true },
title: String,
title_lower: { type: String, es_indexed: true, es_boost: 2.0 },
slug: String,
city: { type: String, es_indexed: true },
country: { type: String, es_indexed: true },
genre: [{ type: String, es_indexed: true }],
description: { type: String, es_indexed: true },
gallery: [{ title: String, images: { thumbnail: String, medium: String, full: String }}],
date: { start: String, end: String },
price: { min: Number, max: Number },
temperature: Number,
weather: String,
comments: [CommentSchema],
lineup: { type: [LineupSchema], es_indexed: true }
Here I want only title_lower, city, genre, description and lineup indexed. But checking elastic like: http://localhost:9200/events/_search I can see that all fields are added under _source.

Resources