prismic-javascript
Version:
JavaScript development kit for prismic.io
967 lines • 231 kB
JSON
{
"page": 2,
"results_per_page": 20,
"results_size": 20,
"total_results_size": 228,
"total_pages": 12,
"next_page": "http://localhost:3000/api/v2/documents/search?ref=WYx9HB8AAB8AmX7z&page=3&pageSize=20",
"prev_page": "http://localhost:3000/api/v2/documents/search?ref=WYx9HB8AAB8AmX7z&page=1&pageSize=20",
"results": [
{
"id": "WW4bKScAAMAqmluX",
"uid": "renaudbressand",
"type": "author",
"href": "http://localhost:3000/api/v2/documents/search?ref=WYx9HB8AAB8AmX7z&q=%5B%5B%3Ad+%3D+at%28document.id%2C+%22WW4bKScAAMAqmluX%22%29+%5D%5D",
"tags": ["tagA", "tagB"],
"first_publication_date": "2017-07-18T14:29:39+0000",
"last_publication_date": "2017-08-10T15:34:52+0000",
"slugs": [
"renaud-bressand"
],
"linked_documents": [],
"lang": "en-us",
"alternate_languages": [],
"data": {
"author": {
"name": {
"type": "Text",
"value": "Renaud Bressand"
},
"description": {
"type": "Text",
"value": "Renaud focuses on user experience and onboarding our users. He also helps out with Support and even codes in @scala. A real Swiss army knife! Passionate about good food as well as a skilled dancer!"
},
"photobogoss": {
"type": "Image",
"value": {
"main": {
"dimensions": {
"width": 180,
"height": 180
},
"alt": null,
"copyright": null,
"url": "https://prismic-io.s3.amazonaws.com/wroom/071a2d77065531fabb2bb887bf74f2a4892b03e1_builder.png"
},
"views": {
}
}
},
"picture-profile": {
"type": "Image",
"value": {
"main": {
"dimensions": {
"width": 180,
"height": 180
},
"alt": null,
"copyright": null,
"url": "https://prismic-io.s3.amazonaws.com/wroom/65661798758002e7f7a6092544fba5ce3dce28df_renaud-bressand.jpg"
},
"views": {
}
}
}
}
}
},
{
"id": "U1kTRgEAAC8A5ldS",
"uid": null,
"type": "faq",
"href": "http://localhost:3000/api/v2/documents/search?ref=WYx9HB8AAB8AmX7z&q=%5B%5B%3Ad+%3D+at%28document.id%2C+%22U1kTRgEAAC8A5ldS%22%29+%5D%5D",
"tags": [
"pricing"
],
"first_publication_date": "2016-08-04T14:21:20+0000",
"last_publication_date": "2017-04-06T14:30:23+0000",
"slugs": [
"is-there-any-storage-or-usage-limit-for-a-content-repository"
],
"linked_documents": [],
"lang": "en-us",
"alternate_languages": [],
"data": {
"faq": {
"question": {
"type": "StructuredText",
"value": [
{
"type": "heading1",
"text": "Is there any storage or usage limit for a content repository? ",
"spans": []
}
]
},
"answer": {
"type": "StructuredText",
"value": [
{
"type": "paragraph",
"text": "There is no hard limit on how much you can store in a production content repository, or on how much you use the Writing Room and the Content Query API.",
"spans": []
},
{
"type": "paragraph",
"text": "However, we've tuned our content repository for fair normal use. We will reach out to you if we think your project will go beyond this. You can also contact us if you have any further inquiries.",
"spans": []
}
]
},
"priority": {
"type": "Number",
"value": 810.0
}
}
}
},
{
"id": "UkTEpLO53-4AY1ER",
"uid": null,
"type": "doc",
"href": "http://localhost:3000/api/v2/documents/search?ref=WYx9HB8AAB8AmX7z&q=%5B%5B%3Ad+%3D+at%28document.id%2C+%22UkTEpLO53-4AY1ER%22%29+%5D%5D",
"tags": [
"api"
],
"first_publication_date": null,
"last_publication_date": null,
"slugs": [
"predicate-operators",
"predicates-syntax"
],
"linked_documents": [
{
"id": "UkTEpLO53-4AY1ER",
"tags": [
"api"
],
"type": "doc",
"slug": "predicate-operators",
"lang": "en-us"
}
],
"lang": "en-us",
"alternate_languages": [],
"data": {
"doc": {
"title": {
"type": "StructuredText",
"value": [
{
"type": "heading1",
"text": "Predicate operators",
"spans": []
}
]
},
"content": {
"type": "StructuredText",
"value": [
{
"type": "heading2",
"text": "Predicate operators",
"spans": []
},
{
"type": "paragraph",
"text": "The operator in a predicate is the part that defines how the fragment is matched to the value. For instance, in the predicate above that we just mentioned, the operator is \"at\", and the operator's namespace is \"root\" (which is the one that you don't have to write):",
"spans": []
},
{
"type": "preformatted",
"text": "[:d = at(document.type, \"product\")]",
"spans": []
},
{
"type": "heading3",
"text": "The root namespace",
"spans": []
},
{
"type": "paragraph",
"text": "Operators on the root namespace tend to be for basic tasks that work for all relevant fragment types.",
"spans": []
},
{
"type": "paragraph",
"text": "The at operator is the equality operator, checking that the fragment matches the described value exactly. It takes as a value:",
"spans": [
{
"start": 4,
"end": 6,
"type": "strong"
}
]
},
{
"type": "list-item",
"text": "either an array of strings if you're applying it on tags, in which case it checks that ALL the listed tags are part of the document;",
"spans": []
},
{
"type": "preformatted",
"text": "[:d = at(document.tags, [\"Macaron\", \"Cupcake\"])]",
"spans": []
},
{
"type": "list-item",
"text": "or a string for any other case (text fragment, document type, document id, ...).",
"spans": []
},
{
"type": "preformatted",
"text": "[:d = at(document.type, \"product\")]",
"spans": []
},
{
"type": "paragraph",
"text": "Warning: you shouldn't apply the \"at\" predicate to a structured text fragment, comparing its value to a full text string, as it won't match it. This is pretty logical: your structured text fragment contains so much more than just its full text value!",
"spans": [
{
"start": 0,
"end": 249,
"type": "em"
}
]
},
{
"type": "paragraph",
"text": "The any operator takes an array of strings as a value. It works exactly the same way as the at operator, but checks whether the fragment matches either one of the values in the array. You can use it with all fragment types; for instance, if you want to get the documents that are either a macaron or a cupcake:",
"spans": [
{
"start": 4,
"end": 7,
"type": "strong"
}
]
},
{
"type": "preformatted",
"text": "[:d = any(document.tags, [\"Macaron\", \"Cupcake\"])]",
"spans": []
},
{
"type": "paragraph",
"text": "The fulltext operator provides two capabilities: either you want to check if a certain string is anywhere inside a document (this is what you should use to make your project's search engine feature), or if the string is contained inside a specific document's structured text fragment. Checking whether a string is contained in the document would therefore look like this:",
"spans": [
{
"start": 4,
"end": 12,
"type": "strong"
}
]
},
{
"type": "preformatted",
"text": "[:d = fulltext(document, \"delight\")]",
"spans": []
},
{
"type": "paragraph",
"text": "And checking whether it is contained in a given structured text fragment would look like this:",
"spans": []
},
{
"type": "preformatted",
"text": "[:d = fulltext(my.product.short_lede, \"delight\")]",
"spans": []
},
{
"type": "paragraph",
"text": "The similar operator is especially smart, since it takes an ID of a document, and returns a list of documents whose contents are similar. This allows to build an automated content discovery feature (for instance, a \"Related posts\" block) at almost no cost. Also, remember that you can combine it with other predicates, and search for the \"similar blog posts\" for instance, of even the \"similar blog posts that mention chocolate\". The additional max parameter allows you to narrow the search in order to get more accurate results; it is especially interesting when you have a lot of documents talking about the same broad subject.",
"spans": [
{
"start": 4,
"end": 11,
"type": "strong"
},
{
"start": 445,
"end": 448,
"type": "em"
}
]
},
{
"type": "preformatted",
"text": "[:d = similar(\"idOfSomeDocument\", 10)]",
"spans": []
},
{
"type": "paragraph",
"text": "The has and missing operators check whether a fragment has a value or not. Note that the missing operator will restrict the results to the type implied in the fragment path.",
"spans": [
{
"start": 4,
"end": 7,
"type": "strong"
},
{
"start": 12,
"end": 19,
"type": "strong"
}
]
},
{
"type": "preformatted",
"text": "[:d = has(my.blog-post.author)]\n[:d = missing(my.blog-post.author)]",
"spans": []
},
{
"type": "heading3",
"text": "The number namespace",
"spans": []
},
{
"type": "paragraph",
"text": "Operators that belong to the number namespace are meant to be applied on number fragments.",
"spans": []
},
{
"type": "paragraph",
"text": "The gt operator tests whether a Number fragment is strictly greater than a numeric value:",
"spans": [
{
"start": 4,
"end": 6,
"type": "strong"
}
]
},
{
"type": "preformatted",
"text": "[[:d = number.gt(my.product.price, 2)]]",
"spans": []
},
{
"type": "paragraph",
"text": "The lt operator tests whether a Number fragment is strictly lower than a numeric value:",
"spans": [
{
"start": 4,
"end": 6,
"type": "strong"
}
]
},
{
"type": "preformatted",
"text": "[[:d = number.lt(my.product.price, 4.2)]]",
"spans": []
},
{
"type": "paragraph",
"text": "The inRange operator tests whether the Number fragment is between two numeric values; this is one of those operators that take more than just one value:",
"spans": [
{
"start": 4,
"end": 11,
"type": "strong"
}
]
},
{
"type": "preformatted",
"text": "[[:d = number.inRange(my.product.price, 2, 4)]]",
"spans": []
},
{
"type": "heading3",
"text": "The date namespace",
"spans": []
},
{
"type": "paragraph",
"text": "Operators that belong to the date namespace are meant to be applied on Date fragments. Values for dates are potentially:",
"spans": []
},
{
"type": "list-item",
"text": "dates following the ISO 8601 standard: \"2013-09-25\"",
"spans": [
{
"start": 39,
"end": 51,
"type": "strong"
}
]
},
{
"type": "list-item",
"text": "datetimes following the ISO 8601 standard: \"2013-11-19T15:30:59z\"",
"spans": [
{
"start": 43,
"end": 65,
"type": "strong"
}
]
},
{
"type": "list-item",
"text": "or a numerical timestamp: 1384872209277",
"spans": [
{
"start": 26,
"end": 39,
"type": "strong"
}
]
},
{
"type": "paragraph",
"text": "All of these formats are allowed when this documentation uses the placeholder <date>.",
"spans": [
{
"start": 78,
"end": 84,
"type": "em"
}
]
},
{
"type": "paragraph",
"text": "The date.before and date.after operators test whether the Date fragment is before/after the specified date:",
"spans": [
{
"start": 4,
"end": 15,
"type": "strong"
},
{
"start": 20,
"end": 30,
"type": "strong"
}
]
},
{
"type": "preformatted",
"text": "[\n [:d = date.after(my.blog-post.publication-date, <date>)]\n [:d = date.before(my.blog-post.publication-date, <date>)]\n]",
"spans": []
},
{
"type": "paragraph",
"text": "The date.between operator tests whether the Date fragment is between the specified two dates:",
"spans": [
{
"start": 4,
"end": 16,
"type": "strong"
}
]
},
{
"type": "preformatted",
"text": "[:d = date.between(my.blog-post.publication-date, <date>, <date>)]",
"spans": []
},
{
"type": "paragraph",
"text": "These three predicates are strict inequalities, in other words the date corresponding to the bounds is not returned in the results. If you need an inclusive query, you should offset the bound by one day. ",
"spans": []
},
{
"type": "paragraph",
"text": "The date.day-of-month operator tests whether the Date fragment matches the specified day of the month. The value must be between 1 and 31.",
"spans": [
{
"start": 4,
"end": 21,
"type": "strong"
}
]
},
{
"type": "preformatted",
"text": "[:d = date.day-of-month(my.blog-post.publication-date, 10)]",
"spans": []
},
{
"type": "paragraph",
"text": "The date.day-of-month-before and date.day-of-month-after operators operators test whether the day of month of the Date fragment is strictly lower/greater than the specified day of the month. The value must be between 1 and 31.",
"spans": [
{
"start": 4,
"end": 28,
"type": "strong"
},
{
"start": 33,
"end": 66,
"type": "strong"
}
]
},
{
"type": "preformatted",
"text": "[\n [:d = date.day-of-month-after(my.blog-post.publication-date, 10)]\n [:d = date.day-of-month-before(my.blog-post.publication-date, 10)]\n]",
"spans": []
},
{
"type": "paragraph",
"text": "The date.day-of-week operator tests whether the Date fragment matches the specified day of the week. The value must either be between 1 and 7, or between \"Monday\" and \"Sunday\".",
"spans": [
{
"start": 4,
"end": 20,
"type": "strong"
}
]
},
{
"type": "preformatted",
"text": "[\n [:d = date.day-of-week(my.blog-post.publication-date, 2)]\n [:d = date.day-of-week(my.blog-post.publication-date, \"Tuesday\")]\n]",
"spans": []
},
{
"type": "paragraph",
"text": "The date.day-of-week-before and date.day-of-week-after operators test whether the day of week of the Date fragment is strictly lower/greater than the specified day of the week. The value must either be between 1 and 7, or between \"Monday\" and \"Sunday\".",
"spans": [
{
"start": 4,
"end": 27,
"type": "strong"
},
{
"start": 32,
"end": 54,
"type": "strong"
}
]
},
{
"type": "preformatted",
"text": "[\n [:d = date.day-of-week-after(my.blog-post.publication-date, 4)]\n [:d = date.day-of-week-before(my.blog-post.publication-date, \"Friday\")]\n]",
"spans": []
},
{
"type": "paragraph",
"text": "The date.month operator tests whether the Date fragment matches the specified month. The value must be either between 1 and 12, or between \"January\" and \"December\".",
"spans": [
{
"start": 4,
"end": 23,
"type": "strong"
}
]
},
{
"type": "preformatted",
"text": "[\n [:d = date.month(my.blog-post.publication-date, 2)]\n [:d = date.month(my.blog-post.publication-date, \"May\")]\n]",
"spans": []
},
{
"type": "paragraph",
"text": "The date.month-before and date.month-after operator tests whether the month of the Date fragment is strictly lower/greater that the specified month. The value must be either between 1 and 12, or between \"January\" and \"December\".",
"spans": [
{
"start": 4,
"end": 21,
"type": "strong"
},
{
"start": 26,
"end": 42,
"type": "strong"
}
]
},
{
"type": "preformatted",
"text": "[\n [:d = date.month-after(my.blog-post.publication-date, 4)]\n [:d = date.month-before(my.blog-post.publication-date, \"December\")]\n]",
"spans": []
},
{
"type": "paragraph",
"text": "The date.year function tests whether the Date fragment matches the specified year.",
"spans": [
{
"start": 4,
"end": 13,
"type": "strong"
}
]
},
{
"type": "preformatted",
"text": "[\n [:d = date.year(my.blog-post.publication-date, 2013)]\n]",
"spans": []
},
{
"type": "paragraph",
"text": "The date.year-before and date.year-after operators test whether the year of the Date fragment is strictly lower/greater that the specified year.",
"spans": [
{
"start": 4,
"end": 20,
"type": "strong"
},
{
"start": 25,
"end": 40,
"type": "strong"
}
]
},
{
"type": "preformatted",
"text": "[\n [:d = date.year-after(my.blog-post.publication-date, 2011)]\n [:d = date.year-before(my.blog-post.publication-date, 2013)]\n]",
"spans": []
},
{
"type": "paragraph",
"text": "The date.hour operator tests whether the Date fragment matches the specified hour. The value must be between 0 and 23.",
"spans": [
{
"start": 4,
"end": 13,
"type": "strong"
}
]
},
{
"type": "preformatted",
"text": "[\n [:d = date.hour(my.blog-post.publication-date, 2)]\n]",
"spans": []
},
{
"type": "paragraph",
"text": "The date.hour-before and date.hour-after operators test whether the hour of the Date fragment is strictly lower/greater than the specified hour. The value must be between 0 and 23.",
"spans": [
{
"start": 4,
"end": 20,
"type": "strong"
},
{
"start": 25,
"end": 40,
"type": "strong"
}
]
},
{
"type": "preformatted",
"text": "[\n [:d = date.hour-after(my.blog-post.publication-date, 17)]\n [:d = date.hour-before(my.blog-post.publication-date, 12)]\n]",
"spans": []
}
]
},
"category": {
"type": "Link.document",
"value": {
"document": {
"id": "UjBe8bGIJ3EKtgBZ",
"type": "documentation-categoy",
"tags": [
"api"
],
"lang": "en-us",
"slug": "api-documentation",
"uid": "api-documentation"
},
"isBroken": false
}
}
}
}
},
{
"id": "Vc34yhwAAIcID8AG",
"uid": null,
"type": "plan",
"href": "http://localhost:3000/api/v2/documents/search?ref=WYx9HB8AAB8AmX7z&q=%5B%5B%3Ad+%3D+at%28document.id%2C+%22Vc34yhwAAIcID8AG%22%29+%5D%5D",
"tags": [
"new"
],
"first_publication_date": null,
"last_publication_date": null,
"slugs": [
"starter",
"small"
],
"linked_documents": [],
"lang": "en-us",
"alternate_languages": [],
"data": {
"plan": {
"name": {
"type": "StructuredText",
"value": [
{
"type": "heading1",
"text": "Starter",
"spans": []
}
]
},
"users": {
"type": "Text",
"value": "3 Users"
},
"price": {
"type": "Number",
"value": 9.0
},
"support": {
"type": "Text",
"value": "Basic Support"
},
"annualPrice": {
"type": "Number",
"value": 7.0
},
"recommended": {
"type": "Select",
"value": ""
},
"features": {
"type": "StructuredText",
"value": [
{
"type": "paragraph",
"text": "All core writing room\nFeatures",
"spans": []
}
]
}
}
}
},
{
"id": "UfeAtt_mqSFd3EEs",
"uid": null,
"type": "argument-feature",
"href": "http://localhost:3000/api/v2/documents/search?ref=WYx9HB8AAB8AmX7z&q=%5B%5B%3Ad+%3D+at%28document.id%2C+%22UfeAtt_mqSFd3EEs%22%29+%5D%5D",
"tags": [
"topargument",
"developers"
],
"first_publication_date": null,
"last_publication_date": null,
"slugs": [
"get-started-in-no-time"
],
"linked_documents": [],
"lang": "en-us",
"alternate_languages": [],
"data": {
"argument-feature": {
"title": {
"type": "StructuredText",
"value": [
{
"type": "heading1",
"text": "Get started in no time",
"spans": []
}
]
},
"catcher": {
"type": "StructuredText",
"value": [
{
"type": "paragraph",
"text": "Get your project up and running in seconds. Nothing to install.",
"spans": []
}
]
},
"priority": {
"type": "Number",
"value": 400.0
},
"image": {
"type": "Image",
"value": {
"main": {
"dimensions": {
"width": 160,
"height": 160
},
"alt": null,
"copyright": null,
"url": "https://prismic-io.s3.amazonaws.com/wroom/a1636efe83467ac13459c2667bb7078acbbac426.png"
},
"views": {
}
}
}
}
}
},
{
"id": "UotrJknM01Itg9Ul",
"uid": "structuring-content-leads-to-powerful-content-query",
"type": "blog",
"href": "http://localhost:3000/api/v2/documents/search?ref=WYx9HB8AAB8AmX7z&q=%5B%5B%3Ad+%3D+at%28document.id%2C+%22UotrJknM01Itg9Ul%22%29+%5D%5D",
"tags": [],
"first_publication_date": null,
"last_publication_date": "2017-07-19T15:00:34+0000",
"slugs": [
"structuring-content-leads-to-powerful-content-query-api",
"prismicio-api",
"api-in-depth"
],
"linked_documents": [
{
"id": "UotrJknM01Itg9Ul",
"tags": [],
"type": "blog",
"slug": "structuring-content-leads-to-powerful-content-query-api",
"lang": "en-us"
},
{
"id": "UotrJknM01Itg9Ul",
"tags": [],
"type": "blog",
"slug": "structuring-content-leads-to-powerful-content-query-api",
"lang": "en-us"
}
],
"lang": "en-us",
"alternate_languages": [],
"data": {
"blog": {
"image": {
"type": "Image",
"value": {
"main": {
"dimensions": {
"width": 700,
"height": 200
},
"alt": null,
"copyright": null,
"url": "https://prismic-io.s3.amazonaws.com/wroom/45d2182ac451d38447db4df81cdee38e099c9da7_wroom2fe6895dfd-e087-4fd5-8660-587f4f7881a5_icon-api-sre.png"
},
"views": {
}
}
},
"title": {
"type": "StructuredText",
"value": [
{
"type": "heading1",
"text": "Structuring Content leads to Powerful Content Query API",
"spans": []
}
]
},
"body": {
"type": "StructuredText",
"value": [
{
"type": "paragraph",
"text": "One of the things that got me interested when joining the prismic.io team, is the possibilities behind the concept of clean separation between content management from one side and the query api from the other side. This is what we call Writing Room and Content Query API.",
"spans": [
{
"start": 0,
"end": 214,
"type": "label",
"data": {
"label": "excerpt"
}
}
]
},
{
"type": "paragraph",
"text": "Not only does it allow content writers to author, manage and publish content with a dedicated tool, but it also opens a lot of possibilities by making all content queryable in all kinds of ways through the API.",
"spans": []
},
{
"type": "paragraph",
"text": "This is why I thought of writing a blog post on how structuring content in the Writing Room enables a powerful query API for finding content and integrating it in projects.",
"spans": []
},
{
"type": "heading2",
"text": "Content structure: breaking content into pieces",
"spans": []
},
{
"type": "paragraph",
"text": "Structuring content simply means going away from authoring opaque, mixed with style, content blocks that can hardly be analyzed. Instead, we cut or structure content documents into more meaningful parts (we call them fragments).",
"spans": []
},
{
"type": "paragraph",
"text": "Let's take an example of a Cup Cake document: instead of creating a huge html document with all the description of a cupcake all mixed together, we rather structure that document to have different fields for title, flavor, price, main image, color, etc.",
"spans": []
},
{
"type": "paragraph",
"text": "Not only we structure our documents in different fields, but we also specify the kinds of these fields: title is text, price is a number, etc. This allows us to better organize our content, and more importantly to further exploit the power of the Content Query Api.",
"spans": []
},
{
"type": "image",
"url": "https://prismic-io.s3.amazonaws.com/wroom/e48c917a296f405334f8a58bc0d41040cb76404c_fragments.png",
"alt": null,
"copyright": null,
"dimensions": {
"width": 700,
"height": 435
}
},
{
"type": "heading2",
"text": "Querying content: retrieve documents",
"spans": []
},
{
"type": "paragraph",
"text": "Now that we structured our cupcake into different fragments. Let's search for pastries with the flavor \"Chocolate\". In prismic.io, we use predicates to express a search. Here is the predicate for finding documents with a flavor:",
"spans": []
},
{
"type": "preformatted",
"text": ":d = at(my.product.flavour, \"Chocolate\")",
"spans": []
},
{
"type": "paragraph",
"text": "Basically here we are saying that we're looking for documents containing \"Chocolate\" in their flavor fragment. In every repository there is an API browser allowing you to experiment with queries on your content. You can try the flavor predicate yourself in the \"Les Bonnes Choses\" API browser.",
"spans": [
{
"start": 94,
"end": 101,
"type": "em"
},
{
"start": 261,
"end": 293,
"type": "hyperlink",
"data": {
"type": "Link.web",
"value": {
"url": "https://prismic.io/docs/how-query-predicates-work"
}
}
}
]
},
{
"type": "paragraph",
"text": "In the structure we described above, we saw that we have a price fragment which is a number. This simply means that we can, for instance, search all products with a specific price:",
"spans": [
{
"start": 163,
"end": 179,
"type": "hyperlink",
"data": {
"type": "Link.web",
"value": {
"url": "https://prismic.io/docs/query-by-field"
}
}
}
]
},
{
"type": "pre