在对象 (ROOT_QUERY) 上找不到字段 allProjects("first":5,"skip":0,"orderBy":"

Posted

技术标签:

【中文标题】在对象 (ROOT_QUERY) 上找不到字段 allProjects("first":5,"skip":0,"orderBy":"updatedAt_DESC")【英文标题】:Can't find field allProjects("first":5,"skip":0,"orderBy":"updatedAt_DESC") on object (ROOT_QUERY)在对象 (ROOT_QUERY) 上找不到字段 allProjects("first":5,"skip":0,"orderBy":"updatedAt_DESC") 【发布时间】:2018-09-13 03:28:28 【问题描述】:

所以我正在尝试创建一个新项目(我的项目中的一个对象),我正在使用 Apollo Client、Angular 5 和 graphcool 框架。

我只想提一下,我的项目已创建并保存在数据库中,但我希望我的应用程序将我重定向到所有项目所在的页面。它正在重定向我,但新项目未显示在列表中。所以我花时间在互联网上阅读教程,发现我需要订阅事件 createProject。所以我这样做了,但是重定向后项目仍然没有显示在列表中,即使它被创建并保存到数据库中也是如此。 我也收到以下错误:

Error: Can't find field allProjects("first":5,"skip":0,"orderBy":"updatedAt_DESC") on object (ROOT_QUERY) 
  "allProjects()": [
    
      "type": "id",
      "generated": false,
      "id": "Project:cjfji3yntbbjh0193m2ijcbzi",
      "typename": "Project"
    ,
    
      "type": "id",
      "generated": false,
      "id": "Project:cjfjjai46blgw0103koujxlex",
      "typename": "Project"
    ,
    
      "type": "id",
      "generated": false,
      "id": "Project:cjfjjezdwbq220193z4bwrgnl",
      "typename": "Project"
    ,
    
      "type": "id",
      "generated": false,
      "id": "Project:cjfjxnqj21fsa01642klbrhsu",
      "typename": "Project"
    
  ],
  "_allProjectsMeta": 
    "type": "id",
    "generated": true,
    "id": "$ROOT_QUERY._allProjectsMeta",
    "typename": "_QueryMeta"
  ,
  "allSkills(\"filter\":\"name_contains\":\"a\")": [
    
      "type": "id",
      "generated": false,
      "id": "Skill:cjee75u5ocggc0169lncmboub",
      "typename": "Skill"
    ,
    
      "type": "id",
      "generated": false,
      "id": "Skill:cjee761gnvzde0195pfemfo05",
      "typename": "Skill"
    ,
    
      "type": "id",
      "generated": false,
      "id": "Skill:cjee767ufb5zx0114yfnj8qnk",
      "typename": "Skill"
    ,
    
      "type": "id",
      "generated": false,
      "id": "Skill:cjee7b9su7jv70145vsbe9g2p",
      "typename": "Skill"
    ,
    
      "type": "id",
      "generated": false,
      "id": "Skill:cjee7bi5rb80k0114dm3dznrx",
      "typename": "Skill"
    ,
    
      "type": "id",
      "generated": false,
      "id": "Skill:cjee7bpwkb82r01148rsqfj0m",
      "typename": "Skill"
    ,
    
      "type": "id",
      "generated": false,
      "id": "Skill:cjee7by8aamj50195fp7n836n",
      "typename": "Skill"
    ,
    
      "type": "id",
      "generated": false,
      "id": "Skill:cjee7c368b87o0114nltmfxey",
      "typename": "Skill"
    ,
    
      "type": "id",
      "generated": false,
      "id": "Skill:cjee7ccpdb8c10114xhea0g4s",
      "typename": "Skill"
    ,
    
      "type": "id",
      "generated": false,
      "id": "Skill:cjefg99anpihz0114wxyz1rk9",
      "typename": "Skill"
    ,
    
      "type": "id",
      "generated": false,
      "id": "Skill:cjefg9vhxohew0191fzyahz88",
      "typename": "Skill"
    ,
    
      "type": "id",
      "generated": false,
      "id": "Skill:cjefgawohp1e00195q18bf7lo",
      "typename": "Skill"
    ,
    
      "type": "id",
      "generated": false,
      "id": "Skill:cjefgb8q9pj430114b7c8nmhb",
      "typename": "Skill"
    ,
    
      "type": "id",
      "generated": false,
      "id": "Skill:cjefgbhhcp1kn0195ewwbfjxy",
      "typename": "Skill"
    ,
    
      "type": "id",
      "generated": false,
      "id": "Skill:cjefgc9wqoi2o0191i2tfnzyd",
      "typename": "Skill"
    ,
    
      "type": "id",
      "generated": false,
      "id": "Skill:cjefgcj4dqthc0115y0nx0vn7",
      "typename": "Skill"
    ,
    
      "type": "id",
      "generated": false,
      "id": "Skill:cjefgcqak7fgl0139phkcm7hj",
      "typename": "Skill"
    ,
    
      "type": "id",
      "generated": false,
      "id": "Skill:cjegyq4dr9auf0182diw0it6b",
      "typename": "Skill"
    ,
    
      "type": "id",
      "generated": false,
      "id": "Skill:cjegyqjb3al1s01204v40lqlj",
      "typename": "Skill"
    ,
    
      "type": "id",
      "generated": false,
      "id": "Skill:cjegyqqazd5xp0121y5mewf8o",
      "typename": "Skill"
    ,
    
      "type": "id",
      "generated": false,
      "id": "Skill:cjegyqvqg58fz0160oh5d3s5p",
      "typename": "Skill"
    ,
    
      "type": "id",
      "generated": false,
      "id": "Skill:cjegyracbd1b50174pbw32u0h",
      "typename": "Skill"
    
  ],
  "allSkills(\"filter\":\"name_contains\":\"ad\")": [
    
      "type": "id",
      "generated": false,
      "id": "Skill:cjee75u5ocggc0169lncmboub",
      "typename": "Skill"
    ,
    
      "type": "id",
      "generated": false,
      "id": "Skill:cjee761gnvzde0195pfemfo05",
      "typename": "Skill"
    
  ]
.
    at readStoreResolver (readFromStore.js:71)
    at executeField (graphql.js:90)
    at eval (graphql.js:46)
    at Array.forEach (<anonymous>)
    at executeSelectionSet (graphql.js:40)
    at graphql (graphql.js:35)
    at diffQueryAgainstStore (readFromStore.js:124)
    at readQueryFromStore (readFromStore.js:37)
    at InMemoryCache.read (inMemoryCache.js:84)
    at InMemoryCache.readQuery (inMemoryCache.js:181)

我正在关注关于 howtographql 的教程,他们正在使用这种方法,所以它有可能做到。

我的架构:

export const CREATE_PROJECT_MUTATION = gql`
  mutation CreateProjectMutation($name: String!,$description: String!, $skillsIds: [ID!],$startedAt: DateTime!, $endingAt: DateTime!,$type: PROJECT_TYPE, $currency: Currency,$createdById: ID!) 
    createProject(
      name: $name,
      description: $description,
      skillsIds: $skillsIds,
      startedAt: $startedAt,
      endingAt: $endingAt,
      type: $type,
      currency: $currency,
      createdById: $createdById
    )
      id,
      name,
      createdBy
        id,
        firstName,
        lastName
      ,
      updatedAt,
      description,
      currency,
      skills
        id,
        name
      ,
      startedAt,
      endingAt,
      type
    
  
`;

export interface CreateProjectMutationResponse 
  loading: boolean;
  createProject: Project;


export const ALL_PROJECTS_QUERY = gql`
  query AllProjectsQuery($first: Int, $skip: Int, $orderBy: ProjectOrderBy)
    allProjects(first: $first, skip: $skip, orderBy: $orderBy)
      id,
      name,
      createdBy
        id,
        firstName,
        lastName
      ,
      updatedAt,
      description,
      currency,
      skills
        id,
        name
      ,
      startedAt,
      endingAt,
      type
    
    _allProjectsMeta 
      count
    
  
`;

export interface AllProjectsQueryResponse 
  allProjects: Project[];
  _allProjectsMeta:  count: number ;
  loading: boolean;


// Subscription when project is created
export const NEW_PROJECTS_SUBSCRIPTION = gql`
  subscription 
    Project(filter: 
      mutation_in: [CREATED]
    ) 
      node 
        id
        name
        createdBy
          id
          firstName
          lastName
        
        updatedAt
        description
        currency
        skills
          id,
          name
        
        startedAt
        endingAt
        type
      
    
  
`;

export interface NewProjectSubcriptionResponse 
  node: Project;

我会把我的课程发给你,以防万一出现问题:

export class Project 
  id: String;
  name: String;
  description: String;
  createdBy: AppUserDisplay;
  updatedAt: Date;
  skills: Skill[];
  startedAt: Date;
  endingAt: Date;
  currency: Currency;
  type: PROJECT_TYPE;


export class AppUserDisplay 
  id: String;
  firstName: String;
  lastName: String;


export class Skill 
  id: String;
  name: String;

我用于创建项目的角度组件:

CreateProject(projForm: NgForm) 
    const createdById = localStorage.getItem(GC_USER_ID);
    if (!createdById) 
      console.error('No user logged in');
      return;
    
    // get the selected project type and replace " " with "_" in the name
    this.project_type = this.project_types[Number.parseInt(this.selected_project_type.toString())].replace(/\s/g, '_');

    // Formating the date
    this.startedAt.setFullYear(this.fromDate.year, this.fromDate.month - 1, this.fromDate.day);
    this.endingAt.setFullYear(this.toDate.year, this.toDate.month - 1, this.toDate.day);

    // Create the project and save it to the database
    const createMutationSubscription = this.apollo.mutate<CreateProjectMutationResponse>(
      mutation: CREATE_PROJECT_MUTATION,
      variables: 
        name: projForm.form.controls.name.value,
        description: projForm.form.controls.description.value,
        skillsIds: this.choosenSkillsIds,
        startedAt: this.startedAt,
        endingAt: this.endingAt,
        type: this.project_type,
        currency: this.currencies[Number.parseInt(this.selected_currency.toString())],
        createdById: createdById
      ,
      update: (store,  data:  createProject  ) => 
        this.updateStoreAfterCreateProject(store, createProject);
      ,
    ).subscribe((result) => 
      // console.log(result);
      this.router.navigate(['/all-projects']);
    , (error) => 
      alert(error);
    );

    this.subscriptions = [...this.subscriptions, createMutationSubscription];
  



updateStoreAfterCreateProject (store, createProject): UpdateStoreAfterCreateProjectCallback 

const data = store.readQuery(
  query: ALL_PROJECTS_QUERY,
  variables: 
    id: createProject.id,
    first: PROJECTS_PER_PAGE,
    skip: 0,
    orderBy: 'updatedAt_DESC'
  
);

const allProjects = data.allProjects.slice();
allProjects.splice(0, 0, createProject);
allProjects.pop();
data.allProjects = allProjects;

store.writeQuery( query: ALL_PROJECTS_QUERY,
  variables: 
    id: createProject.id,
    first: PROJECTS_PER_PAGE,
    skip: 0,
    orderBy: 'updatedAt_DESC'
  , data );

  return;


 

这是我用于显示项目的组件

// When Developer access projects page he can see all projects from db
    const getQuery = (variables): Observable<ApolloQueryResult<AllProjectsQueryResponse>> => 
      const query = this.apollo.watchQuery<AllProjectsQueryResponse>(
        query: ALL_PROJECTS_QUERY,
        variables: 
          id: localStorage.getItem(GC_USER_ID)
        
      );

      query
        .subscribeToMore(
          document: NEW_PROJECTS_SUBSCRIPTION,
          updateQuery: (previous: AllProjectsQueryResponse,  subscriptionData ) => 
            // Casting to any because typings are not updated
            // console.log(<any>subscriptionData);
            const newAllProjects = [
              (<any>subscriptionData).data.Project.node,
              ...previous.allProjects
            ];
            return 
              ...previous,
              allLinks: newAllProjects
            ;
          
        );

      return query.valueChanges;
    ;

    // 6
    const allProjectsQuery: Observable<ApolloQueryResult<AllProjectsQueryResponse>> = Observable
      // 6
      .combineLatest(this.first$, this.skip$, this.orderBy$, (first, skip, orderBy) => ( first, skip, orderBy ))
      // 7
      .switchMap((variables: any) =>  getQuery(variables));
    // 8
    const querySubscription = allProjectsQuery.subscribe((response) => 
      this.projects = response.data.allProjects;
      this.count = response.data._allProjectsMeta.count;
      this.loading = response.data.loading;
    );

这就是我订阅 createProject 事件的方式,但由于某种原因它不起作用。这是我的 apollo 配置文件:

export class GraphQLModule 
  // Inject Apollo and HttpLink
  constructor(apollo: Apollo, httpLink: HttpLink) 

    const token = localStorage.getItem(GC_AUTH_TOKEN);
    const authorization = token ? `Bearer $token` : null;
    const headers = new HttpHeaders().append('Authorization', authorization);

    // Provide the GraphQL endpoint
    const uri = 'https://api.graph.cool/simple/v1/cjeb3hlm13hxw017104lj3x5c';
    const http = httpLink.create( uri, headers );

    // 1
    const ws = new WebSocketLink(
      uri: `wss://subscriptions.graph.cool/v1/cjeb3hlm13hxw017104lj3x5c`,
      options: 
        reconnect: true,
        connectionParams: 
          authToken: localStorage.getItem(GC_AUTH_TOKEN),
        
      
    );

    apollo.create(
      // 2
      link: ApolloLink.split(
        // 3
        operation => 
          const operationAST = getOperationAST(operation.query, operation.operationName);
          return !!operationAST && operationAST.operation === 'subscription';
        ,
        ws,
        http,
      ),
      cache: new InMemoryCache()
    );
  

对不起,我的帖子太长了,我试图解释并尽我所能向您展示我的问题是什么。希望可以有人帮帮我。感谢您的宝贵时间。

【问题讨论】:

【参考方案1】:

好吧,我找到了解决问题的方法,但我不得不说我真的不明白为什么会这样。

首先我的解决方案:

看起来问题是由于某种原因,如果参数没有默认值,apollo 无法找到带参数的查询。所以我所做的就是像这样更改架构:

export const ALL_PROJECTS_QUERY = gql`
  query AllProjectsQuery($first: Int = 5, $skip: Int = 0)
    allProjects(first: $first, skip: $skip, orderBy: updatedAt_DESC)
      id,
      name,
      createdBy
        id,
        firstName,
        lastName
      ,
      updatedAt,
      description,
      currency,
      skills
        id,
        name
      ,
      startedAt,
      endingAt,
      type
    
    _allProjectsMeta 
      count
    
  
`;

如您所见,我删除了参数 orderBy,因为我不知道如何为其设置默认值。所以如果有人知道怎么做,请分享你的知识。因此,我将 orderBy 设置为固定值。

我的 createProject 变异和更新函数现在看起来像这样:

// Create the project and save it to the database
    const createMutationSubscription = this.apollo.mutate<CreateProjectMutationResponse>(
      mutation: CREATE_PROJECT_MUTATION,
      variables: 
        name: projForm.form.controls.name.value,
        description: projForm.form.controls.description.value,
        skillsIds: this.choosenSkillsIds,
        startedAt: this.startedAt,
        endingAt: this.endingAt,
        type: this.project_type,
        currency: this.currencies[Number.parseInt(this.selected_currency.toString())],
        createdById: createdById
      ,
      update: (store,  data:  createProject  ) => 
        this.updateStoreAfterCreateProject(store, createProject);
      ,
    ).subscribe((result) => 
      // console.log(result);
      this.router.navigate(['/all-projects']);
    , (error) => 
      alert(error);
    );

    this.subscriptions = [...this.subscriptions, createMutationSubscription];

updateStoreAfterCreateProject (store, createProject): UpdateStoreAfterCreateProjectCallback 

    const data: any = store.readQuery(
      query: ALL_PROJECTS_QUERY,
      variables: 
        searchText: '',
        first: PROJECTS_PER_PAGE,
        skip: 0,
        orderBy: 'updatedAt_DESC'
      
    );

    console.log(data);
    const allProjects = data.allProjects.slice();
    allProjects.splice(0, 0, createProject);
    allProjects.pop();
    data.allProjects = allProjects;

    store.writeQuery( query: ALL_PROJECTS_QUERY,
      variables: 
        searchText: '',
        first: PROJECTS_PER_PAGE,
        skip: 0,
        orderBy: 'updatedAt_DESC'
      , data );

    return;
  

是的,我知道在变量中添加 orderBy: 'updatedAt_DESC' 变量是没有用的。没有它,它也可以工作,创建项目后更新列表,但我仍然收到该字段的错误

allProjects(first: $first, skip: $skip, orderBy: updatedAt_DESC).......

找不到。所以我决定暂时把它留给他们。

嗯,我希望这会帮助那些和我一样被困在同一个错误中的人。我想提一下,这可能不是最好的解决方案,但我认为在 github 上打开了一个线程作为这个问题的错误。因此,在它没有修复之前,您可以尝试我的解决方法。

【讨论】:

以上是关于在对象 (ROOT_QUERY) 上找不到字段 allProjects("first":5,"skip":0,"orderBy":"的主要内容,如果未能解决你的问题,请参考以下文章

在对象 (ROOT_QUERY) 上找不到字段 allProjects("first":5,"skip":0,"orderBy":"

Thymeleaf:对象中的对象,无法像jsp那样访问值?属性或字段 - 在 null 上找不到

从缓存中读取查询导致在对象未定义上找不到字段 <field>

Apollo GraphQL 客户端“网络错误:在未定义的对象上找不到字段 XXXX”,disableOffline:false

EL1008E: 在“java.util.ArrayList”类型的对象上找不到属性或字段“内容” - 可能不是公共的或无效的?

在“nsstring *”类型的对象上找不到读取字典元素的预期方法