0

Would someone be able to explain how to query Firebase for special characters?

I've got some data like so -

posts
  post_1
    description: "This is a post! #thisdoesntwork"
  post_2
    description: "Heres another post! #neitherdoesthis"

And if I run a query in swift -

let db = Database.database().reference()

db.child("posts").queryOrdered(byChild: "description").queryStarting(atValue: "[a-zA-Z0-9]*").queryEnding(atValue: "#thisdoesntwork").observeSingleEvent(of: .value) { (snapshot) in
   // No results!
 }

Nothing gets returned. However it works when I omit the hashtag like so -

db.child("posts").queryOrdered(byChild: "description").queryStarting(atValue: "[a-zA-Z0-9]*").queryEnding(atValue: "thisdoesntwork").observeSingleEvent(of: .value) { (snapshot) in
   // One post gets returned here
 }

Is this because the hash is a special character I need to escape somehow? Or am I querying for it in the wrong way?

Thanks in advance.

Chris Edgington
  • 2,937
  • 5
  • 23
  • 42
  • Possible duplicate of [Adding Firebase data, dots and forward slashes](https://stackoverflow.com/questions/19132867/adding-firebase-data-dots-and-forward-slashes) – DoesData Oct 20 '17 at 16:16
  • @DoesData That answer is definitely not a duplicate and has unrelated information. The OP is asking about sub string type search. – Jay Oct 21 '17 at 12:52

1 Answers1

1

What you think is happening isn't. Let me explain and provide an example:

It appears your are trying to perform a string search. Perhaps even a substring search.

Firebase does not offer a substring search feature and even a String search isn't exactly a string search as it would be in a language like swift.

So for starters this isn't valid

queryStarting(atValue: "[a-zA-Z0-9]*")

that would literally search for a node that starts with the string or characters equal to [a-zA-Z0-9]*. So if your node happened to look like the following:

posts
  post_x
    description: "[a-zA-Z0-9]* This node would be returned"

it would be a match.

.startWith: a query that starts with the given string
.endWith: a query ending with a string that starts with the given string
        (not the ending part of a string or a substring)

Let me provide an example structure based on your structure

posts
  post_1
    description: "This is a post! #thisdoesntwork"
  post_2
    description: "Heres another post! #neitherdoesthis"
  post_3
    description: "a"
  post_4
    description: "n"

And an example query

    let postsRef = ref.child("posts")
    let queryRef = postsRef.queryOrdered(byChild: "description")
                           .queryStarting(atValue: "This")
                           .queryEnding(atValue: "z")
    queryRef.observeSingleEvent(of: .value) { snapshot in
        print(snapshot)
    }

This query will return posts 1, 3, and 4. why?

post_1 starts with the letter upper case T, which is ascii 84.

The query will return ALL nodes that have an ascii value starting with 84 (ascii T) and ending with 122 (ascii z). So post 3 is an a, which is ascii 97 and post 4, an n, is ascii 110. So all of those are returned.

*for those following along, the query actually starts with the word 'This' and ends with the word 'z' but simplifying for this example.

While on one hand that may seem a bit limiting, it's actually quite powerful.

One use is when you want to query for a range of values starting with a specific string. So let say you own a produce distribution company and have items like Apple, Banana and Peanut and Walnut. You can organize your database like this

items
  item_0
   description: fruit_apple
  item_1
   description: fruit_banana
  item_2
   description: nut_peanut
  item_3
   description: nut_walnut

If you wanted a list of all of your fruits, you can query like so

    let queryRef = postsRef.queryOrdered(byChild: "description")
                           .queryStarting(atValue: "fruit_")
                           .queryEnding(atValue: "fruit_")

This are called compound values.

In your case the bottom line answer is you cannot search directly for special characters within the string however, you can search for a range of characters that start with character within an ascii code range.

query starting at "!" and ending at "/" would return all strings starting with characters:

33  !
34  \"
35  #
36  $
37  %
38  &
39  '
40  (
41  )
42  *
43  +
44  ,
45  -
46  .
47  /

This super long answer isn't really a solution but will maybe help with restructuring your Firebase so you can get to the data you want to query on.

Lance Samaria
  • 17,576
  • 18
  • 108
  • 256
Jay
  • 34,438
  • 18
  • 52
  • 81
  • Thanks Jay. This certainly made me realize I was thinking about this the wrong way. For the record I ended up encoding the hashtags and splitting them out into a different child which I could query much easier. For the full text search I think using something like Algolia would have probably been my best option, but as I'm only using the free Firebase plan for development right now this isn't supported. – Chris Edgington Oct 26 '17 at 08:08