angularfire icon indicating copy to clipboard operation
angularfire copied to clipboard

How do i query a collection with the new change that have been made?

Open yushinzm opened this issue 4 years ago • 8 comments

How do query a firestore collection to find document that meet a certain condition? please find an example of the code below.

import { Firestore, collectionData, collection } from '@angular/fire/firestore';
import { Observable } from 'rxjs';

interface Item {
  name: string,
  ...
};

@Component({
  selector: 'app-root',
  template: `
  <ul>
    <li *ngFor="let item of item$ | async">
      {{ item.name }}
    </li>
  </ul>
  `
})
export class AppComponent {
  item$: Observable<Item[]>;
  constructor(firestore: Firestore) {
    const collection = collection(firestore, 'items');
    this.item$ = collectionData(collection);
  }
}

yushinzm avatar Jan 01 '22 22:01 yushinzm

This issue does not seem to follow the issue template. Make sure you provide all the required information.

google-oss-bot avatar Jan 01 '22 22:01 google-oss-bot

@yushinzm Have you look at https://github.com/angular/angularfire/blob/master/docs/firestore/querying-collections.md

akshaybabloo avatar Jan 02 '22 03:01 akshaybabloo

@yushinzm Have you look at https://github.com/angular/angularfire/blob/master/docs/firestore/querying-collections.md

sorry but a few things have changed if you can assist me in implementing the new version look at the sample code I share you will notice that it's different in the two.

yushinzm avatar Jan 02 '22 08:01 yushinzm

Hey Everyone, Ive been trying to get my head around v7 without too many docs available. Ive come up with code to (well trying too) query a collection and display in Angular (see below): ` async getAppointments() { const userId = await this.auth.currentUser?.uid; console.log('Get Appointments: ' + userId);

const appRef = collection(this.afs, 'appointments')
const appQuery = query(appRef, where('uid', '==', userId));

const querySnapshot = getDocs(appQuery);
this.appt = (await querySnapshot).forEach((d) => {
  const id = d.id;
  const data = d.data as Appointment;
  console.log(id, "=>", data);

  return {id, ...data};
  
})

}`

in the HTML *ngFor="let a of appt | async"

Firestore Timestamp: {{ a.start }}

But nothing shows. Im getting the document ID in the console log . Any ideas will be very helpful.

Thanks

mnc12004 avatar Jan 15 '22 14:01 mnc12004

const appRef = collection(this.afs, 'appointments') const appQuery = query(appRef, where('uid', '==', userId));

const querySnapshot = getDocs(appQuery);

@mnc12004 Thanks for helping me resolve my issue. Here is how I think you can approach your issue

// Please define an Observable like below
appointmentItems: Observable<Appointment[]>; // Appointment being a model


// inside your function
const appRef = collection(this.firestore, 'appointments')
  const appQuery = query(appRef, where('uid', '==', userId));

  this.appointmentItems= (await collectionData(appQuery)).pipe(
    map((actions) => {
      return actions.map((a) => {
        const data = a as Appointment;
        const uid = a.id;
        return { uid, ...data };
      });
    })
  );

Hope this helps, regards.

yushinzm avatar Jan 15 '22 18:01 yushinzm

how do we combine multiple where clauses in this mode ?

dsl400 avatar Jan 21 '22 17:01 dsl400

how do we combine multiple where clauses in this mode ?

I haven't found this in the docs anywhere, but intellisense shows me that these are the parameters for the query function:

query<DocumentData>(query: Query<DocumentData>, ...queryConstraints: QueryConstraint[])

This means that you can chain your where clauses (or any other filter function) like this:

query(appRef, where('uid', '==', userId), where('anotherField', '==', 'some value'))

kylerummens avatar Feb 08 '22 05:02 kylerummens

Thank you guys for helping me with the new query syntax. Still can not believe it is not part of official documentation for such a long time..

pazdernikpavel avatar May 27 '22 08:05 pazdernikpavel

is there any document yet on how to use the query syntax?

simonpeters avatar Dec 13 '22 14:12 simonpeters

https://firebase.google.com/docs/reference/js/firestore_.md#query

amsheehan avatar Mar 26 '23 19:03 amsheehan

collectionData does not return the key like /collections/{documentKey}. if you know what i mean. how do we grab that

MustafaHossaini avatar Apr 17 '23 11:04 MustafaHossaini

I didn't test this but looks like it may work - or at least the starting point for something useful =) EDIT: Made some adjustments and made it work.

import { Component, Inject, inject } from '@angular/core';
import {
  AngularFirestore,
  AngularFirestoreCollection
} from '@angular/fire/compat/firestore';
import {
  DocumentSnapshot,
  OrderByDirection,
  WhereFilterOp,
  getDocs,
  limit,
  orderBy,
  query,
  where
} from '@angular/fire/firestore';
import { collection } from "firebase/firestore";

export interface WhereCondition<T> {
  field: keyof T;
  operator: WhereFilterOp;
  value: T[keyof T];
}

export interface OrderByCondition<T> {
  field: keyof T;
  order?: OrderByDirection;
}

export interface FirestoreQuery<T> {
  limit?: number;
  startAt?: number | string | DocumentSnapshot<T>;
  startAfter?: number | string | DocumentSnapshot<T> | null;
  endAt?: number | DocumentSnapshot<T>;
  endBefore?: number | DocumentSnapshot<T>;
  orderBy?: OrderByCondition<T>[];
  where?: WhereCondition<T>[];
}

export interface BaseEntity {
  id?: string;
}

export interface Tutorial extends BaseEntity {
  id?: string;
  title?: string;
  description?: string;
  published?: boolean;
}

export class BaseFirestoreEntityService<T extends BaseEntity> {
  protected readonly firestore: AngularFirestore = inject(AngularFirestore);
  protected entitiesRef: AngularFirestoreCollection<T>;

  constructor(@Inject('path') private path: string) {
    this.entitiesRef = this.firestore.collection(this.path);
  }

  async search(q: FirestoreQuery<T>) {
    const {where: ws, orderBy: os} = q;

    const orderBys = os?.map((condition) => {
      return orderBy(condition.field as string, condition.order);
    }) ?? [];

    const wheres = ws?.map((condition) => {
      return where(condition.field as string, condition.operator, condition.value);
    }) ?? [];

    // add logic for other query conditions

    const coll = collection(this.firestore.firestore, this.path);
    const queryFn = query(coll, ...wheres, ...orderBys, limit(q.limit ?? 99));
    const results = await getDocs(queryFn)
    return results.docs.map((doc) => {
      return {
        id: doc.id,
        ...doc.data()
      } as T
    });
  }
}

@Component({
  selector: 'app-root',
  templateUrl: './app.component.html',
  styleUrls: ['./app.component.css']
})
export class AppComponent {
  private service = inject(BaseFirestoreEntityService<Tutorial>);
  
  constructor() {}

  async search() {
    const orderByConditions: OrderByCondition<Tutorial>[] = [
      {field: 'title', order: 'desc'}
    ];
    
    const whereConditions: WhereCondition<Tutorial>[] = [
      {field: 'title', operator: '==', value: 'Test 5a'},
    ];

    const results = await this.service.search({orderBy: orderByConditions, where: whereConditions});
    console.log('data', results)
  }
}

vdiaz1130 avatar Apr 19 '23 03:04 vdiaz1130