How to query firestore() for graphQL resolver?

2020-07-23 06:07发布

I'm combining a GraphQL app with my existing Firebase project and am having a lot of problems getting the queries to correctly get data from the firestore().

So far I have the mutations working correctly, but when I go to query the data I can't get the firestore().get() snapshot into a form that graphQL will recognize.

so far it looks like this:

const {GraphQLObjectType,
  GraphQLString,
  GraphQLBoolean,
  GraphQLFloat,
  GraphQLSchema,
  GraphQLID,
  GraphQLList,
  GraphQLNonNull} = require("graphql");
const admin = require('firebase-admin');
const functions = require('firebase-functions');


admin.initializeApp(functions.config().firebase);

//Models
const Room = admin.firestore().collection('room');
const Position = admin.firestore().collection('position');
const Plant = admin.firestore().collection('plant');
const PlantInfo = admin.firestore().collection('plantInfo');

const RoomType = new GraphQLObjectType({
  name: "Room",
  fields: () => ({
    id: { type: GraphQLID },
    name: { type: GraphQLString },
    description: { type: GraphQLString },
    floor: { type: GraphQLString },
    building: { type: GraphQLString },
    positions: {
      type: new GraphQLList(PositionType),
      resolve(parent, arg) {
        //return _.filter(positions, {inRoomId:parent.id})
        return Position.orderByChild('inRoomId').equalTo(parent.id);
      }
    }
  })
});

const PositionType = new GraphQLObjectType({
  name: "Position",
  fields: () => ({
    id: { type: GraphQLID },
    name: { type: GraphQLString },
    description: { type: GraphQLString },
    exposure: { type: GraphQLString },
    size: { type: GraphQLString },
    inRoom: {
      type: RoomType,
      resolve(parent, args) {
        //return _.find(rooms, {id:parent.inRoomId})
        return Room.child(parent.inRoomId);
      }
    }
  })
});

const RootQuery = new GraphQLObjectType({
  name: "RootQueryType",
  fields: {
    room: {
      type: RoomType,
      args: { id: { type: GraphQLID } },
      resolve(parent, args) {
        //code to get data from db/othersourse
        //return _.find(rooms, {id: args.id});
        return Room.child(args.id);
      }
    },
    position: {
      type: PositionType,
      args: { id: { type: GraphQLID } },
      resolve(parent, args) {
        //code to get data from db/othersourse
        //return _.find(positions, {id: args.id})
        return Position.child(args.id);
      }
    },
    rooms: {
      type: new GraphQLList(RoomType),
      resolve(parent, args) {
        //return rooms
        return Room.get().then(snapshot => {snapshot.forEach(doc => {return doc})})

      }
    },
    positions: {
      type: new GraphQLList(PositionType),
      resolve(parent, args) {
        //return positions
        return Position.get().then(doc => console.log(doc)).catch(err => console.log('Error getting document', err));
      }
    }
  }
});

const Mutation = new GraphQLObjectType({
  name: "Mutation",
  fields: {
    addRoom: {
      type: RoomType,
      args: {
        name: { type: new GraphQLNonNull(GraphQLString) },
        floor: { type: new GraphQLNonNull(GraphQLString) },
        building: { type: new GraphQLNonNull(GraphQLString) }
      },
      resolve(parent, args) {
        let room = {
          name: args.name,
          floor: args.floor,
          building: args.building
        };
        return Room.add(room);
      }
    },
    addPosition: {
      type: PositionType,
      args: {
        name: { type: new GraphQLNonNull(GraphQLString) },
        exposure: { type: new GraphQLNonNull(GraphQLString) },
        size: { type: new GraphQLNonNull(GraphQLString) },
        inRoomId: { type: new GraphQLNonNull(GraphQLString) }
      },
      resolve(parent, args) {
        let position = {
          name: args.name,
          exposure: args.exposure,
          size: args.size,
          inRoomId: args.inRoomId
        };
        return Position.add(position);
      }
    }
  }
});

module.exports = new GraphQLSchema({
  query: RootQuery,
  mutation: Mutation
});

Under the RootQuery -> Rooms I'm trying to get a graphQL query to return all the rooms in my 'room' collection. I have been able to get it to console.log() a list of documents using:

return Room.get()
.then(snapshot => {
snapshot.forEach(doc => {
        console.log(doc.id, " => ", doc.data());

But getting this into an array has so far eluded me. Any help is really appreciated.

1条回答
你好瞎i
2楼-- · 2020-07-23 06:36

Seeing as no one was able to answer this, I ended up figuring it out for myself :p

So resolve functions relating to getting a collection of related data for example positions. the following works:

first you need a function to convert the snapshots into an array as this is what graphQL is expecting. This also allows your to seperate the id and add it in with the array item:

const snapshotToArray = (snapshot) => {
  var returnArr = [];

  snapshot.forEach((childSnapshot)=> {
      var item = childSnapshot.data();
      item.id = childSnapshot.id;

      returnArr.push(item);
  });

  return returnArr;
};

Next when getting the data you use .get() which returns a promise (and error) which can be passed into the snapshotToArray().

return Position.get().then((snapshot) => {
          return snapshotToArray(snapshot);
        }) 

For resolve functions that only call on one dataset for example inRoom. Its similar to the first one except using .where() and seperating the id and data() in the snapshot functions:

return Room.doc(parent.inRoomId).get().then((snapshot) => {
          var item = snapshot.data();
          item.id = snapshot.id;
          return item;
        })

Just incase someone else runs into the same problem :)

查看更多
登录 后发表回答