Nested type without referencing another schema in Mongoosastic - elasticsearch

I want to give a nested field the elastic mapping type "nested" by using Mongoosastic. I also want to specify the es_type of the fields in the nested field.
My schema looks like this:
const CarOwner = new Schema({
cars: [{
name: {
type: String,
es_indexed: true,
},
price: {
type: Number,
es_indexed: true,
es_type: 'float'
},
}],
});
I want this ElasticSearch mapping:
{
"mappings": {
"carowner": {
"properties": {
"cars": {
"type": "nested",
"properties": {
"name": { "type": "text" },
"price": { "type": "float" },
}
}
}
}
}
}
The only Mongoosastic examples I've found looks like this:
var Car = new Schema({
name: {
type: String,
es_indexed: true,
},
price: {
type: Number,
es_indexed: true,
es_type: 'float'
},
})
var CarOwner = new Schema({
cars: {
type:[Car],
es_indexed: true,
es_type: 'nested',
es_include_in_parent: true
}
})
Do I have to create a subschema or is there any way I could use Mongoosastic to create the mapping I want?

Related

How to create custom resolvers for Gatsby page queries?

I have a Gatsby application pulling data from Sanity.
This is Sanity's schema for the course.js:
import video from './video'
export default {
// Computer name
name: `courses`,
// Visible title
title: `Courses`,
type: `document`,
fields: [
{
name: `title`,
title: `Course title`,
type: `string`,
description: `Name of the course`
},
{
name: `slug`,
title: `slug`,
type: `slug`,
options: {
source: `title`,
maxLength: 100,
}
},
{
name: `price`,
title: `Price`,
type: `number`
},
{
name: `thumbnail`,
title: `Thumbnail`,
type: `image`,
options: {
hotspot: true,
}
},
{
name: `playlist`,
title: `Playlist`,
type: `array`,
of: [
{
title: `Video`,
name: `video`,
type: `video`,
}
]
},
]
}
And this is Sanity's schema for video.js:
export default {
// Computer name
name: `video`,
// Visible title
title: `Video`,
type: `object`,
fields: [
{ name: `title`, type: `string`, title: `Video title` },
{ name: `url`, type: `url`, title: `URL` },
{ name: `public`, title: `public`, type: `boolean`, initialValue: false }
]
}
This Gatsby page query:
{
allSanityCourses {
nodes {
title
price
playlist {
url
title
public
}
}
}
}
Results in:
{
"data": {
"allSanityCourses": {
"nodes": [
{
"title": "Master VS Code",
"price": 149,
"playlist": [
{
"url": "https://www.youtube.com/watch?v=PRz1Nv9GUzs",
"title": "Introduction",
"public": true
},
{
"url": "https://www.youtube.com/watch?v=PRz1Nv9GUzs",
"title": "Philosophy",
"public": false
},
{
"url": "https://www.youtube.com/watch?v=PRz1Nv9GUzs",
"title": "Tech and Tools",
"public": false
},
{
"url": "https://www.youtube.com/watch?v=PRz1Nv9GUzs",
"title": "Integration",
"public": true
},
{
"url": "https://www.youtube.com/watch?v=PRz1Nv9GUzs",
"title": "Extensions",
"public": false
}
]
}
]
}
},
"extensions": {}
}
To prevent the url field from being injected into the React component this Gatsby page query runs on (because these urls are paid for), I need to remove it, if the public field is set to false.
I've tried inserting this into gastby-node.js:
exports.createSchemaCustomization = ({ actions, schema }) => {
const { createTypes } = actions
const typeDefs = [
schema.buildObjectType({
name: "SanityCourses",
fields: {
playlist: {
type: "[SanityVideo]",
url: {
type: "String",
resolve: (source) => "nope"
},
},
},
interfaces: ["Node"],
}),
]
createTypes(typeDefs)
}
And:
exports.createResolvers = ({ createResolvers }) => {
const resolvers = {
SanityCourses: {
playlist: {
type: "[SanityVideo]",
url: {
type: "String",
resolve(source, args, context, info) {
return "nope"
},
}
},
},
}
createResolvers(resolvers)
}
But neither seems to work. The url field returns the url as always. The resolvers don't even seem to fire (I've tried putting console.log()'s in them).
Any help on how to remove the url field if the public field is set to false, or general direction to go in would be very appreciated.
Ditch the attempt in createSchemaCustomization since you don't need to customize the schema here (though I believe there is a way to achieve what you want using it, it is not expected that the data in it is sourced from existing nodes, and this undeclared dependency can create caching issues).
Then update your createResolvers function to something like this:
exports.createResolvers = ({ createResolvers }) => {
createResolvers({
SanityVideo: {
safeUrl: {
type: "String",
resolve: (source, args, context, info) => source.public ? source.url : null
},
},
})
}
I don't believe resolvers can replace schema-originated nodes (fields), hence using safeUrl instead of url
The type you are adding a field to is SanityVideo, and it doesn't matter what the parent node is—this will apply to all instances of SanityVideo in your data

schema type for an unknown object in graphql

I have the following object coming back from db:
{
"total_rows": 200,
"bookmark": "g1AAAABteJzLYWBgYMpgTmEQTM4vTc5ISXIwNDLXMwBCwxyQVCJDUv3___-zMpjc7D8wgEEiCx71eSwgJQ1A6j-GtiwA6MscCg",
"rows": [
{
"id": "51a1ff51b3b4719d05e40ac4bb0d0566",
"objects": {
"0": {
"type": "ipv4-addr",
"value": "192.168.1.10",
"resolves_to_refs": "2"
},
"1": {
"type": "network-traffic"
}
}
],
"counts": {
"created_by_ref": {
"0203a7e6-b174-4af9-812d-ab889816e868": 1,
"0250789a-14c3-4751-b4a0-c017af82b8f1": 1,
"03c63db6-2a84-4627-88be-a83208d524e6": 1,
"05cba3da-11ff-4a7a-aae9-0b1614cd5300": 1,
"fc825d33-26ea-4563-9478-2e1887b87112": 1
},
"file.hashes.MD5": {
"UNDEFINED": 200
},
"file.name": {
"UNDEFINED": 200
},
"ipv4_addr.value": {
"127.0.0.1": 200,
"192.168.1.10": 200
},
"last_observed": {
"1583503380000": 5,
"1583589780000": 9,
"1585749840000": 12
}
},
"num_of_rows": 10
}
I am trying to fit in a graphql schema to the above. I have the following which works paryially:
const graphql = require("graphql");
const { GraphQLObjectType, GraphQLString, GraphQLSchema, GraphQLInt, GraphQLList } = graphql;
const SearchResultType = new GraphQLObjectType({
name: "SearchResult",
fields: ()=>({
total_rows: { type: GraphQLInt },
bookmark: { type: GraphQLString },
//rows: { type: new GraphQLList(GraphQLInt) },
num_of_rows: { type: GraphQLInt }
})
});
const RootQuery = new GraphQLObjectType({
name: "RootQueryType",
fields: {
searchResult:{
type: SearchResultType,
args: { id: { type: GraphQLString } },
resolve(parentValue: any, args: any) {
console.log(args)
return resultMock;
}
}
}
});
module.exports = new GraphQLSchema({
query: RootQuery,
});
The above works for those data types which are defined. However there are some objects in the mockResult above like:
"objects": {
"0": {
"type": "ipv4-addr",
"value": "192.168.1.10",
"resolves_to_refs": "2"
},
"1": {
"type": "network-traffic"
}
or
"counts": {
"created_by_ref": {
"0203a7e6-b174-4af9-812d-ab889816e868": 1,
"0250789a-14c3-4751-b4a0-c017af82b8f1": 1,
"03c63db6-2a84-4627-88be-a83208d524e6": 1,
"05cba3da-11ff-4a7a-aae9-0b1614cd5300": 1,
"fc825d33-26ea-4563-9478-2e1887b87112": 1
So as you see these objects keys are random or at least not guessable until we receive them. Is there any way I can define a sth like this: rows: { type: new GraphQLList(any random object we do not know ) }, as a type in schema below:
const SearchResultType = new GraphQLObjectType({
name: "SearchResult",
fields: ()=>({
total_rows: { type: GraphQLInt },
bookmark: { type: GraphQLString },
rows: { type: new GraphQLList(any random object we do not know ) },
num_of_rows: { type: GraphQLInt }
})
});
You can use the GraphQL JSON Scalar (for example from this implementation). I would not recommend doing this though (in fact years ago I did a talk "GraphQL JSON Scalar considered harmful"). Instead, you might want to transform map-like objects into lists of key-value pairs.
So for example for your counts object you could do the following:
type CreatedByRef {
key: ID
count: Int
}
Object.keys(counts.created_by_ref).map(key => ({
key,
count: counts.created_by_ref[key],
}));
This will change the shape of the result but preserve all the properties of GraphQL.

Subobject is not parsed graphql with golang

The object itself inside the object is parsed with an empty field.
input:
{
Products(search: {limit: 1, filters: {product_id: {gte: 5}}}) {
data {
product_id
product_name
sales_history{
total_check
}
}
}
}
output:
{
"data": {
"Products": {
"data": [
{
"product_id": 35,
"product_name": "testpr",
"sales_history": {}
}
]
}
}
}
Product type:
gql.ProductType = graphql.NewObject(graphql.ObjectConfig{
Name: "Product",
Fields: graphql.Fields{
"product_id": &graphql.Field{
Type: graphql.Int,
},
"product_name": &graphql.Field{
Type: graphql.String,
},
"sales_history": &graphql.Field{
Type: gql.SalesHistoryType,
},
},
})
SalesHistory type:
gql.SalesHistoryType = graphql.NewObject(graphql.ObjectConfig{
Name: "sales_history",
Fields: graphql.Fields{
"total_check": &graphql.Field{
Type: graphql.Float,
},
},
})
In Resolve returning map in interface:
map[data:[map[product_id:35 product_name:testpr sales_history:map[total_check:671.20]]]]
I create the map"sales_history" myself, otherwise opposite the field sales_history - null
The problem was in the packaging of the final map.
It was wrong:
tmp := make(map[string]interface{}, 0)
tmp["total_check"] = v["total_check"]
v["sales_history"] = tmp
*Some fields are hidden
That`s right:
v["sales_history"] = make(map[string]interface{}, 0)
v["sales_history"].(map[string]interface{})["total_check"] = v["total_check"]

How can we hide zero value from text box if field type is number in kendo-ui?

I have a field with Project Code and type as a number but while rendering in the browser it shows default value as 0. So how should I hide or remove zero?
I am new to Kendo-UI. So I am not getting any idea.
schema: {
data: "data", total: "total",
model: {
id: "id",
fields: {
SBU: { type: "string" },
Project_Code: { type: "number" },
Role: { type: "string" },
IPM_Oracle_UserID: { type: "string" },
IQ_LoginID: { type: "string" }
}
}
}
Here in the above coa de, there is "Project_Code" field which has type as number but on browser the default value it render is zero. So, how to hide/remove default value zero for "Project_Code" field.
I found the answer after some searching.Just you need add nullable as true. Please find below re-framed code of mine.
schema: {
data: "data", total: "total",
model: {
id: "id",
fields: {
SBU: { type: "string" },
Project_Code: { type: "number", nullable: true },
Role: { type: "string" },
IPM_Oracle_UserID: { type: "string" },
IQ_LoginID: { type: "string" }
}
}
}

How to allow kendo grid to bind to an undefined field

I have this json object
{
id: string,
name: string,
category: {
id: string
name: string,
}
}
I want to have column that bind to productCategory.name. However that field is nullable. When productCategory is null/undefined, kendo will throw error. How can i tell kendo that if field is undefined, just show empty string?
EDIT
Below is my sample data
[{
"id":1,
"name":"Spaghetti",
"category":{
"id":"1",
"name":"Food"
}},
{
"id":2,
"name":"Coca-cola",
"category":null
}}]
Below is my kendo datasource
var kendoDataSource = new kendo.data.DataSource({
schema: {
data: "data",
total: "total",
model: {
id: "id",
fields: {
id: { type: "string" },
name: { type: "string" },
"category.name": { type: "string" }
}
}
}
});
Data above will throw "undefined" error, because second product does not have category.
Try using empty object instead of null
created a fiddle,check this:
http://jsfiddle.net/Sowjanya51/h930jcru/
Just provide a default value in your model like this:
var kendoDataSource = new kendo.data.DataSource({
schema: {
data: "data",
total: "total",
model: {
id: "id",
fields: {
id: { type: "string" },
name: { type: "string" },
"category.name": { type: "string" },
category: { defaultValue: {
id: "",
name: "",
}
}
}
}
}
});
This will initialize productCategory if it is null or undefined.

Resources