Stitches Introduction
Stitches is a content repository that allows content to be defined, stored, deleted, versioned, searched and be put through a variety of other operations. Stitches allows you to define what represents what a piece of "content" is. This is accomplished by the use of a "Content Definition". A "Content Definition" consists of some summary information to indicate what the content definition represents (i.e. a Product vs. Person). For example, it could represent a product, a zipcode, a person, or even a company. The important thing to remember is that content can actually be comprised of many different attributes. Each attribute would be a string, integer, Boolean, double, PDF, image file—anything. If you are familiar with Drupal and its Custom Content Type, Stitches is similar in spirit.
As a simple example, one could create a content definition that represents a product. The content definition would have individual string attributes for the SKU, name and description. It would have a PDF document attribute to store manufacturer specifications, and it could have one or more image attributes associated with the product. Images are top level attributes in Stitches, in that, if you define an attribute as an Image, you can perform additional operations on this attribute. For example, Stitches will automatically create scaled images for your Image attributes on request. While Stitches is flexible enough to allow you to maintain three different images of a product if it is warranted (an n-number of images for a car, front, back, sides), you have only a single product image (remember, this could be a person’s profile photo!), you could allow Stitches to generate the scaled images that you need. All you need to do is pass the width and attributes that you desire for the image to the stitch service.
Example of Product Content Definition
- SKU (string)
- Description (String)
- image (Image)
- Price (Double)
- Name (String)
- Width (Integer)
- Length (Integer)
- Weight (Integer)
- Manufacturer Specification (PDF)
Content Definition
A Content Definition consists of one or more attributes. Each attribute can be of type, Integer, Boolean, String, PDF, Image, binary, double, Range or Date.
A content definition is a fundamental part of Stitches, and one needs to create a content definition in order to store content in Stitches. Once you have created a content definition in the system, it of course can be reused as much as you want. The Stitches API and application allows you to create and edit Content Definitions.
Content
Once you have a Content Definition and have associated attributes to it, you are ready to create your content. The "Content" that you create in Stitches is associated to a content definition, a set of folders and a set of content versions. To create a "Content", you need to specify the Content Definition that you want the content to be. The content needs to know that it's going to be a Product vs. a Person so that it can enforce the attributes that you defined and allows it to be searched and stored correctly. The content can be associated to "Folders"—Folders are an optional part of Stitches. You can use them or not use them. Folders allow content to be into logical folder structures, just like the Windows/Unix file systems. Folders are hierarchical—they have parents and children. They can be multi-parented. Folders are a nice way for your application to provide a filtered view of your content. For example, you could store each user's content into a separate folder. When each user conducts a search, you can pass the top level folder for the user as a parameter to your search and the Stitches results will be limited to the content contained in that folder and its children folders. Pretty awesome!
The content object in Stitches represents the information that will not be versioned. For example, if you move a MS Word document, it wouldn’t make sense to maintain two versions of the document—each in the different folder. Folders represent a permanent state of a content object and as such, folders are maintained at the content object level, vs. at the content version level. In addition to the folders associated to content, the name and content definition are immutable. That is, they can't be changed once the content has been created. To recap, create your content definition, associate attributes to the content definition. With the content definition, you can create content. Content can be associated to folders.
In addition to folders, the content object is associated to content versions. The content version represents a version of your defined content. That is, it will contain the actual data values for your content. A quick example of this would be that you created a content definition called "Person" with the attributes birthdate and pay grade. You create a content object called "John Smith". Then, you create a content version, and set the birthdate attribute to "05-01-1960" and the pay grade attribute to "More than me". I would normally put a first and last name attribute on the person content definition, but did not want to confuse you since I named the Content "John Smith". You could certainly retrieve content by name (i.e. findContentByName('John Smith')). This content name field is usually so you can identify it in admin tools and use it in API calls.
Content Version
The content version holds all the data values for your content. Along with holding all the data values (i.e. "05-01-1960"), a content version can be associated with one or more tags. Tags are just values that you can create and associate to content so that you can filter by it. For example, you can create a tag called "Featured Person" and assign this tag to one of more content versions that you would like to feature. The Stitches Query API allow you to specify one or more tags to restrict query results. Tags and Folders are similar in that they both allow you to filter by them. The key difference between the two is that Folders are not versioned whereas Tags are versioned. The last key difference between the Tag and the Folder is that the folder is hierarchical and the Tag is not (it is flat).
As explained above, Content Versions hold each of the values that you have stored with their attributes. An important thing to bear in mind is that while Stitches stores all the values for each of your content versions, it will only put the current content version into its search engine. Here’s another way to explain this: If it has a Person content version with the first name attribute of "John" and then you modify the first name attribute to "Bob", you will not be able to do a keyword search on “John" and have this content be returned. The previous content version is still stored, and can even be viewed and rolled back, but until this content version becomes the "current" content version, it will not be returned in any of the Stitches search API results.
Keyword Searching
We touched briefly upon keyword searching. All content that is stored in Stitches is available to search via keyword. In the soon to be released feature, this will be configurable on a per attribute configuration. In addition to indexing the simple String attribute values of a content version, Stitches will extract the text of any PDF documents and keyword searching can be performed against the extracted PDF text. In the near future, integration with Apache Tika project will allow the extraction of text from all available attributes including but not limited to (MS Word, MS PowerPoint, EXIF Image attributes, Visio diagrams, etc.).
Geo Location Searching
Another super-cool feature of Stitches (I am modest, LOL), is its geo searching capability. There is an attribute type called a "LongLat" that can be associated to your content definition. If you assign a LongLat to your content definition, you will be able to store longitude and latitude values for your content. Now you can do "nearby searches" of your content. The Stitches Search API supports passing a radius (distances in miles as a double value) along with an originating longitude/latitude pair. Stitches will return your content items, from closest to farthest distance sorted order. A practical example of this could be that you have a set of hotels (using your content type of Hotel) that have attributes such as photos, address, zip code, and LongLat. Now you can code an application that will search your stitch repository and return the closest hotels to your user. Furthermore, you can still restrict by keyword, and by tags. So you could perform the following logical query "Give me hotels in a 10 mile radius of longitude value x and latitude value y and have the following tags (i.e. pool, free breakfast) and have the following words in the content (i.e. "best value").
Amazon S3 Integration
Amazon S3 integration is accomplished through the Amazon S3 plugin. In Stitches, a Content Attribute of type binary can be configured to be pushed to Amazon S3. If an AttributeValue is added to Stitches (using the aforementioned Attribute), an entry will be made to the S3Asset table that the Amazon S3 plugin works with. Anytime this AttributeValue is modified/deleted, the S3Asset table will be updated. If an AttributeValueRequest is made to the Stitches web service, the returned AttributeValue will be provided by the local repository, not the Amazon S3 value. However, these values should be the same. If a request to retrieve an AttributeValue is made that references an Amazon S3 asset, the ViewContentController will send a permanent redirect to the URL of the S3Asset on the Amazon S3 service.
Deployment Models
Stitches can be deployed either as a standalone service, or as plugin into a Grails application.
- The standalone service describes the case in which you deploy the Stitches plugin into a Grails application that is not the same application that you will be accessing the repository from. In this case, you would create a Grails application and install the Stitches plugin. You would access this Grails application from your other Grails application as a "client" using the web services that the Stitches plugin exposes. Everything that you see in the cookbook is able to be achieved via the web service calls. A lot of additional care has been given to the creation of XFire mapping files and unit tests that actually exercise the API from an outside Grails application. In the near future, PHP and DotNet example clients will be provided. Once your stitches server is running, you would be able to acccess the wsdl at the following URL (you will have to adjust to your application path) http://localhost:8080/stitch-test/services/stitches?wsdl There is a client example application that can be downloaded from SVN here.
- Please note that if you kick off the 2 versions of grails, you will need to run the second application (your stitches client) on a different port. Start the stiches-client example app with "grails -Dserver.port=9090 run-app"
- If you deploy the plugin into your grails application, this means the database/index and all the "workings" of the stitches repository would be on the same machine and exist in the same JVM as your running grails application.
Stitches leverages the following technologies (besides the awesome grails foundation)
- Compass (with Lucene)
- LocalLucene for GEO search
- PDFBox for PDF indexing
- Searchable plugin
- ImageTools plugin
- XFire plugin (if you want use stitches as a web service)
- Amazon-S3 Plugin
Stitches has the following objects
Content Def, a content def serves as a definition for your content. It consists of a name, and it's associated with a set of attributes.
- Create ContentDef
Attribute, represent a property of your content. An attribute has a name, a data type, a boolean to indicate if it's single or multiple valued
- Add attribute to contentdef
- Remove attribute from contentdef
Content- this is an instance of a content def
- Create a content instance
Content Version- each version of content is a content version. Each content item is linked to a set of content versions
- Create a content version
AttributeValue- This is a value for the attribute for a given content version instance
- Save AttributeValues
- Remove AttributeValues
- Retrieve AttributeValues
- Categories:

