How to query documents in docpad based on arrays of objects

1.2k Views Asked by At

I have DocPad documents that look like this:

---
categories: [{slug: ""}, {slug: ""}, ...]
---

Document content.

How can I query all documents which have a predefined slug value in the meta.category array?

3

There are 3 best solutions below

0
On BEST ANSWER

There's a few ways we can go about this.

Via a Template Helper and Query Engine's setFilter

https://gist.github.com/4556245

The most immediate way is via a getDocumentsWithCategory template helper that utilises Query Engine's setFilter call that allows us to specify a custom function (our filter) that will be executed against each model in the collection and based on it's boolean return value keep the model or remove it from the collection.

The downsides of this solution are:

  • We have to redefine our category information in each post
  • We have no immediate method of being able to get information about all the categories available to us

Via Template Helpers and the parseAfter event

https://gist.github.com/4555732

If we wanted to be able to get information on all the categories available to us, but still had the requirement of defining our categories every single time for each post, then we can use the parseAfter event to hook into the meta data for our documents, extract the categories out into a global categories object, and then update our document's categories with id references instead.

Downside is that we still have to have redundant category information.

Via Template Helpers and a global categories listing

https://gist.github.com/4555641

If we wanted to only define our category information once, and then just reference the categories ids within our posts, then this solution is most ideal.

1
On

I manage to create a "foo" collection for a given slug value "bar in docpad.coffee:

collections:
  foo: (database) ->
    database.findAllLive().setFilter("search", (model, value) ->
      categories = model.get('categories')
      return false unless Array.isArray categories
      for category in categories
        if (category.slug and category.slug == value)
          return true
      return false
    ).setSearchString("bar")

but when I try to create a helper function that returns a collection given the array meta ("categories"), the key ("slug") and value ("bar") of the object :

createCollection: (meta, key, value) ->
  result = @getDatabase().createLiveChildCollection()
    .setFilter("search2", (model, searchString) ->
      objects = model.get(meta)
      return false unless Array.isArray objects
      for object in objects
        if (object[key] and object[key] == searchString)
          return true
      return false
    ).setSearchString(value)

i get an empty collection when i try to call it.

1
On

I don't have a drop in solution, but have you seen the source code for the blog of docpad's author? There are some examples of querying for the existence of a metadata object attribute. Hope that helps!