Roy Tang

Programmer, engineer, scientist, critic, gamer, dreamer, and kid-at-heart.

Blog Notes Photos Links Archives About

We have a search application using MarkLogic node.js. We use parsedQuery like this:

            qb.parsedFrom(prop.search, 
            qb.parseBindings(
                qb.word('name', qb.bind('name')),
                qb.word('birthdate', qb.bind('birthdate')),
                qb.range('count', qb.datatype('float'), qb.bind('count'))
            )
        )

The above currently supports search syntax like “count GT 50”, etc. We would like to support searching using a derived value such as age. That is, we want to support a search syntax like “age GT 10”, where the age value is not stored in the documents in the database but rather needs to be computed from the birthdate on the fly. We can’t store the age in the documents since the age changes depending on the current date.

Is this possible and if so, how? If it matters, we are using ML8

Comments

You should be able to change that binding in this way:

qb.word('birthdate', qb.bind('age'))

But I assume you can’t change qb.word to qb.value() as the birthdate has a different format than what you’d like to search on (1990-01-01 vs 20 for example). Can you please confirm?

The way to do this is with a custom constraint. The parse function constructs a cts query based on the parameters. To support something like “age GT 10”, you’d want to build something like

cts:element-range-query(
  xs:QName("date-of-birth"), "<=", 
  fn:current-date() - xs:yearMonthDuration("P10Y")
)

You’ll need a date range index on date-of-birth.

Once you’ve build that custom constraint, you can call it from the MarkLogic Node.js Client API. See Using a Custom Constraint Parser. There’s an example in the Node Developer’s Guide, too.