Ich habe ein kleines Node-Projekt (einfache Ratespielbasis für Standorte), um ein React-Frontend zu bedienen. Es verwendet einen Apollo-Server, um Daten aus einer AWS RDS MySQL-Datenbank mit knex als Abfrage-Generator abzurufen. Ich kann erfolgreich Daten aus einer einzelnen Tabelle abrufen, aber wenn die Abfrage einen Join enthält, ist das untergeordnete Objekt in graphql immer null.
Wenn ich lokal auf den Knotenserver zugreife und die Daten nach Vermutungen abfrage, habe ich die Vermutungsdaten , aber die zugehörigen Benutzer- und Fragendaten sind immer null, wie das Bild zeigt.
Hier ist der Code - Ich habe einen Teil des überschüssigen Codes für die Abfragen entfernt, die einwandfrei funktionieren.
Datenbank
CREATE TABLE `question` (
`id` int NOT NULL AUTO_INCREMENT,
`lat` float NOT NULL,
`lng` float NOT NULL,
`question` varchar(255) DEFAULT NULL,
PRIMARY KEY (`id`)
);
CREATE TABLE `guess` (
`id` int NOT NULL AUTO_INCREMENT,
`lat` float NOT NULL,
`lng` float NOT NULL,
`question_id` int NOT NULL,
`user_id` int NOT NULL,
PRIMARY KEY (`id`),
KEY `user_id` (`user_id`),
KEY `question_id` (`question_id`),
CONSTRAINT `guess_ibfk_1` FOREIGN KEY (`user_id`) REFERENCES `user` (`id`),
CONSTRAINT `guess_ibfk_2` FOREIGN KEY (`question_id`) REFERENCES `question` (`id`)
);
CREATE TABLE `user` (
`id` int NOT NULL AUTO_INCREMENT,
`username` varchar(11) NOT NULL,
`icon` varchar(11) NOT NULL,
`score` int NOT NULL DEFAULT '0',
PRIMARY KEY (`id`)
);
Apollo Server-Anwendung
index.js
const { ApolloServer } = require("apollo-server");
const typeDefs = require("./schema");
const mapDatabase = require("./datasources/map");
const resolvers = require("./resolver");
const knexConfig = {
client: "mysql",
connection: {
host: "my-server",
user: "my-username",
password: "my-password",
database: "db-name",
},
};
const server = new ApolloServer({
typeDefs,
resolvers,
dataSources: () => ({
mapDatabase: new mapDatabase(knexConfig),
}),
});
// The `listen` method launches a web server.
server.listen().then(({ url }) => {
console.log(`Server ready at ${url}`);
});
schema.js
const { gql } = require("apollo-server");
const typeDefs = gql`
type User {
id: ID!
username: String
icon: String
score: Int
}
type Question {
id: ID!
lat: Float
lng: Float
question: String
}
type Guess {
id: ID!
lat: Float
lng: Float
question: Question
user: User
}
type Query {
guesses(question: Int!): [Guess]
}
`;
module.exports = typeDefs;
resolver.js
module.exports = {
Query: {
guesses: (_, { question }, { dataSources }) =>
dataSources.mapDatabase.getGuessesByQuestion(question),
},
};
Datenquellen / map.js
const { SQLDataSource } = require("datasource-sql");
class MapDatabase extends SQLDataSource {
getGuessesByQuestion(question) {
return this.knex
.select("*")
.from("guess AS g")
.leftJoin("user AS u", "u.id", "g.user_id")
.leftJoin("question AS q", "q.id", "g.question_id")
.where("g.question_id", "=", question);
}
}
Nur zur Überprüfung der Integrität habe ich die Abfrage in der Datenbank ausgeführt, um sicherzustellen, dass die zugehörigen Ergebnisse vorliegen und alles wie erwartet wiederhergestellt wird.
SELECT * FROM guess g
LEFT JOIN user u ON u.id = g.user_id
LEFT JOIN question q ON a.id = g.question_id
WHERE g.question_id = 1;
Das Problem ist, dass Ihre Abfrage flache Daten zurückgibt, während Ihre impliziten GraphQL-Resolver eine verschachtelte Objektstruktur erwarten würden. ZB würde knext so etwas zurückgeben:
{
id: 1,
lat: 89.4,
lon: -12.6,
user_id: 2,
username: "user",
icon: "x",
score: 3
}
Aber Sie würden so etwas brauchen, damit der Resolver "nur funktioniert".
{
id: 1,
lat: 89.4,
lon: -12.6,
user: {
id: 2,
username: "user",
icon: "x",
score: 3
}
}
Denken Sie daran: Wenn Sie keinen Resolver an ein Feld übergeben, wird der Standard-Resolver verwendet, der versucht, auf die Feldnamen-Eigenschaft des Objekts zuzugreifen. Das user
Feld hätte also den folgenden Standardauflöser:
parent => parent.user
In der flachen Struktur gibt es kein Feld, daher wird zurückgegeben undefined
-> Die Abfrage gibt für das Feld null zurück. In der verschachtelten Struktur wird ein gültiges Benutzerobjekt zurückgegeben.
Sie können das Ergebnis entweder mithilfe von SQL JSON-Funktionen erstellen oder einen benutzerdefinierten Resolver implementieren für Guess.user
:
module.exports = {
Query: {
guesses: (_, { question }, { dataSources }) =>
dataSources.mapDatabase.getGuessesByQuestion(question),
},
Guess: {
user: (parent) => ({
id: parent.user_id,
username: parent.username,
icon: parent.icon,
score: parent.score
}),
}
};
Dieser Artikel stammt aus dem Internet. Bitte geben Sie beim Nachdruck die Quelle an.
Bei Verstößen wenden Sie sich bitte [email protected] Löschen.
Lass mich ein paar Worte sagen