Я размещал свои данные, используя сервер json на localhost:3000
(API REST) и используя GraphQL для извлечения данных, и теперь я хотел бы переместить данные на сервер Elastic Search, и я все еще хочу использовать GraphQL в качестве APIшлюз.Я попробовал эту библиотеку graphql-compose-elasticsearch
, чтобы использовать GraphQL в качестве прокси для ElasticSearch.https://github.com/graphql-compose/graphql-compose-elasticsearch
В моей исходной схеме GraphQL я определил типы, корневой запрос, преобразователи.Код выглядит так:
const graphql = require('graphql');
const axios = require('axios');
const {
GraphQLObjectType,
GraphQLList,
GraphQLID,
GraphQLInt,
GraphQLString,
GraphQLBoolean,
GraphQLSchema,
GraphQLNonNull
} = graphql;
const RoomType = new GraphQLObjectType({
name: 'RoomType',
fields: () => ({
id: { type: GraphQLID },
roomName: { type: GraphQLString },
roomNumber: { type: GraphQLString },
floorId: { type: GraphQLInt },
hasImages: { type: GraphQLBoolean },
hasGLTF: { type: GraphQLBoolean },
hasPhotogrammetry: { type: GraphQLBoolean },
hasPointClouds: { type: GraphQLBoolean },
roomDescription: { type: GraphQLString },
floor: {
type: FloorType,
resolve(parentValue, args) {
return axios
.get(`http://localhost:3000/floors/${parentValue.floorId}`)
.then((resp) => resp.data);
}
},
assets: {
type: new GraphQLList(AssetType),
resolve(parentValue, args) {
return axios
.get(`http://localhost:3000/rooms/${parentValue.id}/assets`)
.then((resp) => resp.data);
}
}
})
});
const FloorType = new GraphQLObjectType({
name: 'FloorType',
fields: () => ({
id: { type: GraphQLID },
floorName: { type: GraphQLString },
floorDescription: { type: GraphQLString },
rooms: {
type: new GraphQLList(RoomType),
resolve(parentValue, args) {
return axios
.get(`http://localhost:3000/floors/${parentValue.id}/rooms`)
.then((resp) => resp.data);
}
}
})
});
const AssetType = new GraphQLObjectType({
name: 'AssetType',
fields: () => ({
id: { type: GraphQLID },
category: { type: GraphQLString },
assetName: { type: GraphQLString },
assetNumber: { type: GraphQLString },
roomId: { type: GraphQLString },
location: { type: GraphQLString },
isHeritageAsset: { type: GraphQLBoolean },
hasImages: { type: GraphQLBoolean },
hasGLTF: { type: GraphQLBoolean },
hasPhotogrammetry: { type: GraphQLBoolean },
hasPointClouds: { type: GraphQLBoolean },
assetDescription: { type: GraphQLString },
room: {
type: RoomType,
resolve(parentValue, args) {
return axios
.get(`http://localhost:3000/rooms/${parentValue.roomId}`)
.then((resp) => resp.data);
}
}
})
});
const RootQuery = new GraphQLObjectType({
name: 'RootQueryType',
fields: {
getRoom: {
type: RoomType,
args: { id: { type: new GraphQLNonNull(GraphQLID) } },
resolve(parentValue, { id }) {
return axios.get(`http://localhost:3000/rooms/${id}`).then((resp) => resp.data);
}
},
getFloor: {
type: FloorType,
args: { id: { type: new GraphQLNonNull(GraphQLID) } },
resolve(parentValue, { id }) {
return axios.get(`http://localhost:3000/floors/${id}`).then((resp) => resp.data); //to make it compatible between axios and graphql, a workaround
}
},
getAsset: {
type: AssetType,
args: { id: { type: new GraphQLNonNull(GraphQLID) } },
resolve(parentValue, { id }) {
return axios.get(`http://localhost:3000/assets/${id}`).then((resp) => resp.data); //to make it compatible between axios and graphql, a workaround
}
},
getAllRooms: {
type: new GraphQLList(RoomType),
resolve() {
return axios.get(`http://localhost:3000/rooms`).then((resp) => resp.data);
}
},
getAllAssets: {
type: new GraphQLList(AssetType),
resolve() {
return axios.get(`http://localhost:3000/assets`).then((resp) => resp.data);
}
},
getAllFloors: {
type: new GraphQLList(FloorType),
resolve() {
return axios.get(`http://localhost:3000/floors`).then((resp) => resp.data);
}
}
}
});
//expose this to the rest of the application
module.exports = new GraphQLSchema({
query: RootQuery
});
Для Elasticsearch версия 7.0.Я работаю на localhost:9200
, и у меня есть 3 индекса, rooms
, floors
и assets
, и у каждого индекса есть сопоставление.Я пытался кодировать так:
const graphql = require('graphql');
const graphql_compose_elasticsearch = require('graphql-compose-elasticsearch');
const { elasticApiFieldConfig, composeWithElastic } = graphql_compose_elasticsearch;
const { GraphQLSchema, GraphQLObjectType } = graphql;
const elasticsearch = require('elasticsearch');
// Mapping obtained from ElasticSearch server
const floor_mapping = {
properties: {
floorId: {
type: 'text',
fields: {
keyword: {
type: 'keyword',
ignore_above: 256
}
}
},
hasGLTF: {
type: 'boolean'
},
hasImages: {
type: 'boolean'
},
hasPhotogrammetry: {
type: 'boolean'
},
hasPointClouds: {
type: 'boolean'
},
roomDescription: {
type: 'text',
fields: {
keyword: {
type: 'keyword',
ignore_above: 256
}
}
},
roomName: {
type: 'text',
fields: {
keyword: {
type: 'keyword',
ignore_above: 256
}
}
},
roomNumber: {
type: 'text',
fields: {
keyword: {
type: 'keyword',
ignore_above: 256
}
}
}
}
};
const room_mapping = {
//similar
};
const asset_mapping = {
//similar
};
const Room = composeWithElastic({
graphqlTypeName: 'RoomType',
elasticIndex: 'rooms',
elasticType: '_doc',
elasticMapping: room_mapping,
elasticClient: new elasticsearch.Client({
host: 'http://localhost:9200',
apiVersion: '7.0'
})
});
const Floor = composeWithElastic({
graphqlTypeName: 'FloorType',
elasticIndex: 'floors',
elasticType: '_doc',
elasticMapping: floor_mapping,
elasticClient: new elasticsearch.Client({
host: 'http://localhost:9200',
apiVersion: '7.0'
})
});
const Asset = composeWithElastic({
graphqlTypeName: 'AssetType',
elasticIndex: 'assets',
elasticType: '_doc',
elasticMapping: asset_mapping,
elasticClient: new elasticsearch.Client({
host: 'http://localhost:9200',
apiVersion: '7.0'
})
});
const schema = new GraphQLSchema({
query: new GraphQLObjectType({
name: 'Query',
fields: {
roomSearch: Room.getResolver('search').getFieldConfig(),
roomSearchConnection: Room.getResolver('searchConnection').getFieldConfig(),
elastic70: elasticApiFieldConfig({
host: 'http://localhost:9200',
apiVersion: '7.0'
})
}
})
});
module.default = { schema };
server.js выглядит так:
const graphqlHTTP = require('express-graphql');
const { schema } = require('./schema/schema_es');
// const schema = require('./schema/schema');
var cors = require('cors');
const server = require('express')();
//allow cross-origin
server.use(
'/',
cors(),
graphqlHTTP({
schema: schema,
graphiql: true,
formatError: (error) => ({
message: error.message,
stack: error.stack.split('\n')
})
})
);
const PORT = process.env.PORT || 6060;
server.listen(PORT, () => console.log(`Server started on port ${PORT}`));
Я перезапустил серверы, и вот ошибка, которую я получил invariant.esm.js:31 [GraphQL error]: Message: GraphQL middleware options must contain a schema., Location: undefined, Path: undefined
Понятия не имею, как преобразовать схему graphql, rootquery..etc в запрос ES с помощью этого graphql-compose-elasticsearch
, любая помощь приветствуется!