0

Is it possible to get all documents where the ID contains a certain value. I'm using Angular 7.

I tried db.collection('items').where.. but this is not supported.

Example

(collection)
/items
     (doc)
     /green apple
     /red apple
     /banana
     /melon

Can I do a query on the collection 'items' to retrieve all the docs where the ID contains 'apple'. I can't seem to find a working solution.

Doug Stevenson
  • 297,357
  • 32
  • 422
  • 441
rafbanaan
  • 579
  • 3
  • 8
  • 28
  • Are you saying you just want to fetch the document by its unique id? No need for a query to do that. – Doug Stevenson Dec 12 '18 at 19:42
  • I'd defer to @DougStevenson, but my suggestion would be to create a field in the doc that matches the name (and probably skip the custom names in favor of google-generated gibberish), then query on that name-field value. – danh Dec 12 '18 at 19:46
  • @danh The "gibberish", as you say, is actually important when you don't have a uniquely identifiable string to represent a document. You use it when you need it, but there's no obligation if you already have a unique id. That said, coming up with unique strings is not always that easy or convenient. – Doug Stevenson Dec 12 '18 at 19:49
  • Thanks @DougStevenson. I didn’t mean gibberish in a pejorative sense, more whimsically to refer to system generated unique id. I think the op really needs a field for query, rather than (or in addition to) a readable name. – danh Dec 12 '18 at 19:52
  • Firestore allow prefix-matching, but does not have a "contains" operator. So unless "apple" is at the start, what you're looking for is not possible with a query. See https://stackoverflow.com/questions/47115422/is-there-a-way-to-search-sub-string-at-firestore – Frank van Puffelen Dec 12 '18 at 19:59
  • Ok thank you for the answers. – rafbanaan Dec 13 '18 at 07:37
  • @DougStevenson I want to fetch all the docs that match the contains. I'm not using the auto ID for the doc, since I wanted unique docs so they get updated or skipped if a new doc came with that ID. – rafbanaan Dec 13 '18 at 07:40

1 Answers1

0

Here's what I'd do: When creating (or updating) the doc, use the string that you would have used as the title to create another property, maybe call it searchTerms:

let docName = 'green apple';
let ref = /* some path */.collection('items').doc();  // optionally use docName here
let doc = { /* however you initialize your doc */ }

doc.searchTerms = docName.split(' ').reduce((acc, term) => {
      acc[term] = true;
      return acc;
    }, {});
    // that will set searchTerms to { 'green':true, 'apple':true }

ref.set(doc)

Later, you can query those docs like this:

let targetTerm = 'apple'
let key = `searchTerms.${targetTerm}`;
let query = /* some path */.collection('items').where(key, '==', true)

In August, the product introduced support for searching arrays, so you can skip the reduce when creating the object, and ask where-contains on the query, like this:

// as before
doc.searchTerms = docName.split(' ');
ref.set(doc)

and later:

let targetTerm = 'apple'
let query = /* some path */.collection('items').where('searchTerms', 'array-contains', targetTerm)

You might also use a cloud trigger onCreate to build the search terms field, so all the points in code where creation is done can not worry about this.

danh
  • 62,181
  • 10
  • 95
  • 136