【问题标题】:Typing of return type after mongodb projectionmongodb投影后返回类型的类型
【发布时间】:2021-09-19 17:30:11
【问题描述】:

我正在 rust 中制作一个 graphql 解析器,并且只从我的 mongodb 数据库中的 graphql 查询中获取字段。然而,Rust 抱怨说,当然,获取的数据现在与指定的返回类型不属于同一类型。做这样的事情的正确方法是什么。

我想我可以做到#[serde(default)],但这并不完全符合预期(我稍后会解释)

use async_graphql::*;
use serde::{Deserialize, Serialize};
use mongodb::{bson::doc, bson::oid::ObjectId, options::FindOptions, Collection};

#[derive(SimpleObject, Serialize, Deserialize, Debug)]
#[graphql(complex)]
struct Post {
    #[serde(rename = "_id")]
    pub id: ObjectId,
    pub title: String,
    // I could do something like
    // #[serde(default)]
    pub body: String,
}

#[ComplexObject]
impl Post {
    async fn text_snippet(&self) -> &str {
        let length = self.body.len();
        let end = min(length, 5);
        &self.body[0..end]
    }
}

struct Query;
#[Object]
impl Query {
    // fetching posts
    async fn posts<'ctx>(&self, ctx: &Context<'ctx>) -> Vec<Post> {
        let posts = ctx.data_unchecked::<Collection<Post>>();
        let projection = // getting the projection doc here based on graphql fields, lets say doc! {"title": 1}

        let options = FindOptions::builder().limit(10).projection(projection).build();
        let cursor = posts.find(None, options).await.unwrap();

        cursor.try_collect().await.unwrap_or_else(|_| vec![])
    }
}

但是当我运行查询时

{
    posts {
        id
        title
        textSnippet
    }
}

我明白了

thread 'actix-rt:worker:0' panicked at 'called `Result::unwrap()` on an `Err` value: Error { kind: BsonDecode(DeserializationError { message: "missing field `body`" }), labels: [] }', server/src/schema/post.rs:20:46
note: run with `RUST_BACKTRACE=1` environment variable to display a backtrace

当我在正文上执行#[serde(default)] 的内容,然后我查询 textSnippet 而不是正文时,textSnippet 是一个空字符串。

我该如何解决这个问题?

【问题讨论】:

    标签: mongodb rust graphql


    【解决方案1】:

    您能否用OptionPost 中的每个字段包装起来,并让try_collect 为您填充返回的字段?

    【讨论】:

      【解决方案2】:

      您可以使用您需要的那些文件创建一个结构并使用新结构的集合。

      use async_graphql::*;
      use serde::{Deserialize, Serialize};
      use mongodb::{bson::doc, bson::oid::ObjectId, options::FindOptions, Collection};
      
      #[derive(SimpleObject, Serialize, Deserialize, Debug)]
      #[graphql(complex)]
      struct Post {
          #[serde(rename = "_id")]
          pub id: ObjectId,
          pub title: String,
          // I could do something like
          // #[serde(default)]
          pub body: String,
      }
      
      #[derive(SimpleObject, Serialize, Deserialize, Debug)]
      #[graphql(complex)]
      struct PostTitle {
          #[serde(rename = "_id")]
          pub id: ObjectId,
          pub title: String,
      }
      
      struct Query;
      #[Object]
      impl Query {
          // fetching posts
          async fn posts<'ctx>(&self, ctx: &Context<'ctx>) -> Vec<PostTitle> {
              let posts = ctx.data_unchecked::<Collection<PostTitle>>();
              let projection = doc! {"title": 1}
      
              let options = FindOptions::builder().limit(10).projection(projection).build();
              let cursor = posts.find(None, options).await.unwrap();
      
              cursor.try_collect().await.unwrap_or_else(|_| vec![])
          }
      }
      

      【讨论】:

      • 是的,那么你需要提前知道你会做什么查询。我需要它更灵活。
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2021-06-25
      • 1970-01-01
      • 2015-10-21
      • 1970-01-01
      相关资源
      最近更新 更多