Log in |
This product is the realization of a feature that I have wanted to have in Zope since I started using it. ZCatalogs are an integral part of Zope development especially any time you store content or data in the ZODB, which I find myself doing all the time. Although getting data indexed in a catalog is quite easy, getting the data back out with anything but the simplest criteria is a chore. The biggest limitation is the inability with the built in query mechanism to do "or" logic across multiple indexes. Range searches are also kludgey (but at least doable). The goal of this product is to solve the problem of easily extracting data from a catalog using an easy to understand query language that can represent arbitrary query logic intuitively. This has been accomplished by adding (through a hotfix) a new "query" method to ZCatalog. Through this method, you can pass query strings to return matching catalog result sets. The ImplementationThere is actually a large amount of "hidden" functionality that DC has stuffed into ZCatalog, indexes and the BTree data structures deep in the bowels of Zope. My product does not really invent any of this functionality, it just exposes what was already there and previously inaccessible. A major design goal was to not have to make changes to the basic code underlying the ZCatalog and indexes. Although I was skeptical that I could accomplish this at first, in the end this goal was realized. This product changes nothing about the way that ZCatalogs function under the hood. it merely adds a new interface to functionality that already existed. Because this product is a hotfix, it can be uninstalled by simply removing the product directory from your Zope installation. Performing ZCatalog QueriesOk, lets look at how this puppy works! As I mentioned, this product adds a new method named "query" to ZCatalog. It takes two arguments: the query string, and an optional mapping or namespace object to be used in evaluating expressions embedded in the query. Calling from DTML:
Calling from Python scripts: Query LanguageThe query language is designed to look very much like a Python expression. If you are more familiar with SQL than Python, it will look much like a WHERE clause in a SQL statement. The basic syntax is: Let’s look at a few basic query examples: Returns all objects where the index "title" matches "spam". The exact behavior depends on the type of index (TextIndex, FieldIndex, KeywordIndex). This is equivilant to: Let’s extend that a bit: This is equivilant to: OK, so far we haven’t done anything that we couldn’t do before, but how about this: or this: Catalog Query OperatorsLet’s take a look at the operators available to you in query expressions:
These operators are the same as in Python excepting the addition of the "between" operator. Let’s look at using it in a query: This is equivilant to: If I never see the latter one again it will be too soon! 8^) Expressions in QuerysAs I mentioned earlier, you can write an expression for the value for the index to match against. If you want to pass names from the namespace into your queries, you will need to pass REQUEST or _ as the second argument to the query method. Let’s looks at another example with bobobase_modification_time: This returns all objects modified in the last 30 days. The value is calculated by using ZopeTime function. You must pass _ as the second argument for the query machinery to be able to access ZopeTime. The only limitation on expressions is that they cannot contain the "and" or "or" Python operators. Instead use "&" and "|" respectively. DTML Quoting ConundrumsThe keen eyed amongst you may have already noticed a hangup when trying to match against string values in a catalog query from DTML. Since the query itself is a string inside of the expr="..." attribute, single and double quotes are already accounted for before we even get to the query string. Here is an illustration of the problem, take the query: You cannot write this into DTML and have it work: nor can you write this: (and triple-quotes don’t work either) There are two solutions, one built into Zope and one that I came up with. The first is to "escape" the single quotes using backslashes (\): I find this to be quite ugly, but it does work. Another solution that
I added was the ability to delimit string with double back-quotes ( Still not 100% the best, but an improvement. Internally, the double back-quotes are replaced with real double-quotes (") before being fed to the query parser. If anyone has a better idea on how to implement this, let me know. To avoid this problem altogether, use Python Scripts! Things That Are MissingThis being the first release and all, there are things that I would like to see added (feel free to suggest other improvements or contribute code).
I hope you enjoy using query expressions. If you have a comment, suggestion, critique or bug to tell me about, send me an email at: [email protected] |