12

データベースから過剰な情報を取得する必要がないように、クエリと mongdb プロジェクションを操作するクリーンな方法を見つけようとしています。だから私が持っていると仮定:

// the query
type Query {
  getUserByEmail(email: String!): User
}

そして、物事を単純にするために、 Userwith と がemailあります。usernameクエリを送信し、メールのみを取得したい場合は、次の操作を実行できます。

query { getUserByEmail(email: "test@test.com") { email } }

しかし、リゾルバーでは、私の DB クエリは引き続き と の両方usernameを取得しますemailが、そのうちの 1 つだけがクエリ結果として apollo サーバーから返されます。

クエリが要求するものだけをDBに取得させたい:

// the resolver
getUserByEmail(root, args, context, info) {
  // check what fields the query requested
  // create a projection to only request those fields
  return db.collection('users').findOne({ email: args.email }, { /* projection */ });
}

もちろん問題は、クライアントが何を要求しているかについての情報を取得するのがそれほど簡単ではないことです。

リクエストをコンテキストとして渡すと仮定するとcontext.payload、クエリ文字列を持つ (hapi.js) を使用して、さまざまな.split()s を検索することを検討しましたが、それはちょっと汚い感じがします。私が知る限りinfo.fieldASTs[0].selectionSet.selections、フィールドのリストがあり、そこに存在することを確認できました。これがどれほど信頼できるかはわかりません。特に、より複雑なクエリを使い始めたとき。

もっと簡単な方法はありますか?

mongDB を使用しない場合、プロジェクションは、何を取得するかを明示的に伝えるために渡す追加の引数です。

// telling mongoDB to not retrieve _id
db.collection('users').findOne({ email: 'test@test.com' }, { _id: 0 })

いつものように、すばらしいコミュニティに感謝します。

4

5 に答える 5

0

info引数から MongoDB プロジェクションを生成できます。これがあなたが従うことができるサンプルコードです

 /**
 * @description - Gets MongoDB projection from graphql query
 *
 * @return { object }
 * @param { object } info
 * @param { model } model - MongoDB model for referencing
 */

function getDBProjection(info, model) {
  const {
    schema: { obj }
  } = model;
  const keys = Object.keys(obj);
  const projection = {};

  const { selections } = info.fieldNodes[0].selectionSet;

  for (let i = 0; i < keys.length; i++) {
    const key = keys[i];
    const isSelected = selections.some(
      selection => selection.name.value === key
    );

    projection[key] = isSelected;
  }

  console.log(projection);
}

module.exports = getDBProjection;

于 2020-02-19T07:04:09.853 に答える