davidgtonge / backbone_query

A lightweight query api for Backbone Collections

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

Search on nested properties

brasic opened this issue · comments

Given a collection consisting of models like

{
  "title": "post title",
  "content": "post content",
  "id": "1", 
  "comments": [
    {    
      "text": "comment 1 content"
    },
    {    
      "text": "comment 2 content"
    }
  ]
}

I'd like to be able to query against the text inside the nested array, in addition to the text in the toplevel attributes. Currently I'm doing this server-side using a mongo query against the nested property like:

find(
  "$or"=>[
    {:title          => /#{query}/i},
    {:content        => /#{query}/i},
    {"comments.text" => /#{query}/i}
  ]
)

Is it possible or planned to approximate this behavior with backbone_query?

Hi, do be able to search for nested properties you'd probably need to use something like https://github.com/powmedia/backbone-deep-model

This is a simple drop in replacement for Backbone models, so you extend your models from Backbone.DeepModel rather than Backbone.Model. This should work fine with Backbone Query and will enable you to perform the query like this:

text_search = { $likeI: text_string }

MyCollection.query $or:
  title: text_search
  content: text_search
  "comments.text": text_search

$likeI is a quick way to do case insensitive searches. You could of course use regex if you prefer:

regex = /#{text_string}/i

MyCollection.query $or:
  title: regex
  content: regex
  "comments.text": regex

Perfect, thanks!

Actually, I've had another look at your data and the method above wouldn't work as the comments property is an array. So you wouldn't actually need Backbone Deep Model and you could implement a solution like this:

regex = new RegExp text_string, "i"

MyCollection.query $or:
  title: regex
  content: regex
  comments: $cb: (comments) ->
    _(comments).any (comment) -> regex.test comment.text

I'll have a look and see if I can implement a more generic way of doing this.

Excellent -- I didn't think to use a callback to search inside the array. Thanks very much!

I've just pushed a new feature that implements an $elemMatch operator similar to MongoDB. So your query can now be performed like this:

regex = new RegExp text_string, "i"

MyCollection.query $or:
  title: regex
  content: regex
  comments: 
    $elemMatch: 
      text: regex 

Please let me know how you get on.

Very cool. It works perfectly -- much faster than the round trip to the server to gather the same data.

findByName: (query) ->
  isLikeQuery = { $likeI: query } 
  matches = app.posts.query
    $or:
      title:    isLikeQuery
      content:  isLikeQuery
      comments:
        $elemMatch:
          text: isLikeQuery
  @reset matches

Glad its working well for you.