{"__v":10,"_id":"574c389e281b010e00008fee","category":{"project":"54774d9af3736008009e9e0e","version":"56a0bd9e3697d80d002ac5e7","_id":"5735a52431a73b1700887ca0","__v":0,"sync":{"url":"","isSync":false},"reference":false,"createdAt":"2016-05-13T09:57:56.274Z","from_sync":false,"order":13,"slug":"data-objects","title":"Data Objects"},"parentDoc":null,"project":"54774d9af3736008009e9e0e","user":"54774c47f3736008009e9e0c","version":{"__v":20,"_id":"56a0bd9e3697d80d002ac5e7","project":"54774d9af3736008009e9e0e","createdAt":"2016-01-21T11:14:38.131Z","releaseDate":"2016-01-21T11:14:38.131Z","categories":["56a0bd9f3697d80d002ac5e8","56a0bd9f3697d80d002ac5e9","56a0bd9f3697d80d002ac5ea","56a0bd9f3697d80d002ac5eb","56b098a43a5b810d00745e3f","56b098da8f7a4f0d0029dd10","56d5a8ecf612b80b00fb69cd","570989853ab43c0e0072b2d6","571006aa10300c0e007f6133","5735a52431a73b1700887ca0","5744b0529e045c0e00b7a7a2","5744b1d0b56d431700d8a4fb","5744b1fb55d65a0e00b436e1","5744b218f9c7411700ce560e","5744b220f9c7411700ce560f","5744b2259e045c0e00b7a7a7","5744b22cf8b79f0e00de6a2d","5744b23155d65a0e00b436e4","5744b242c758290e00fbc235","5744b2569e045c0e00b7a7a8","5756a3f2bb92962900dafe3d","57ee23e81e42900e0014a42f","581c822c98676e0f00d240ef"],"is_deprecated":false,"is_hidden":false,"is_beta":false,"is_stable":true,"codename":"Sockets","version_clean":"1.1.0","version":"1.1"},"updates":[],"next":{"pages":[],"description":""},"createdAt":"2016-05-30T12:57:02.940Z","link_external":false,"link_url":"","githubsync":"","sync_unique":"","hidden":false,"api":{"results":{"codes":[]},"settings":"","auth":"required","params":[],"url":""},"isReference":false,"order":2,"body":"Chapter Sections:\n1. [Overview](#overview)\n2. [Setting up indexing](#setting-up-indexing)\n3. [Filtering Data Objects](#filtering-data-objects)\n4. [Examples of filtering Data Objects](#examples-of-filtering-data-objects)\n5. [Ordering Data Objects](#ordering-data-objects)\n6. [Using paging with filtering and ordering](#using-paging-with-filtering-and-ordering)\n7. [Summary](#summary) \n[block:api-header]\n{\n  \"type\": \"basic\",\n  \"title\": \"Overview\"\n}\n[/block]\nOnce you have your data in place, you might want to get it from the Syncano Platform. To make things easier and more flexible we allow filtering and ordering of the Data Objects that you make `GET` requests on. \n[block:api-header]\n{\n  \"type\": \"basic\",\n  \"title\": \"Setting up indexing\"\n}\n[/block]\nTo be able to perform filtering or ordering on Data Objects, you should first add appropriate indexes to the Data Class Schema.\n[block:callout]\n{\n  \"type\": \"warning\",\n  \"body\": \"Without proper indexes added to the Data Objects fields in Data Class Schema, filtering or ordering will not work!\"\n}\n[/block]\nAs an example, we will use a data class named Book, with following fields:\n[block:code]\n{\n  \"codes\": [\n    {\n      \"code\": \"Book {\\n  year : integer, //year it was published\\n  num_of_pages : integer, // number of pages\\n  title: string, //book title\\n  intro: text, //introduction to the book - requires longer text\\n  author: string, //name of the author\\n  category: string //category name\\n}\",\n      \"language\": \"json\"\n    }\n  ]\n}\n[/block]\nIf you wanted to filter and order on a `year` field (to e.g. get all books published after year 2010 and sort by year), you would have to have `order_index` and `filter_index` set to `true` in Data Class Schema:\n[block:image]\n{\n  \"images\": [\n    {\n      \"image\": [\n        \"https://files.readme.io/7a1c702-Screen_Shot_2016-08-11_at_17.55.11.png\",\n        \"Screen Shot 2016-08-11 at 17.55.11.png\",\n        977,\n        949,\n        \"#f7f7f7\"\n      ]\n    }\n  ]\n}\n[/block]\n\n[block:code]\n{\n  \"codes\": [\n    {\n      \"code\": \"{ \\n  \\\"name\\\": \\\"year\\\",\\n  \\\"type\\\": \\\"integer\\\", \\n  \\\"order_index\\\": true, \\n  \\\"filter_index\\\": true\\n}\",\n      \"language\": \"json\"\n    }\n  ]\n}\n[/block]\n\n[block:callout]\n{\n  \"type\": \"info\",\n  \"body\": \"You can read more about Data Class Schemas [here](doc:classes).\"\n}\n[/block]\n\n### Filtering and ordering of the default Data Object fields\nThere are several default fields in a Data Object (the ones that you don't define in schema, but they are created for you). Some of these fields can be ordered and filtered but you don't have to add indexing to these fields. \n\nThese are the operations that you can perform on the default Data Object fields:\n[block:parameters]\n{\n  \"data\": {\n    \"0-0\": \"`id`\",\n    \"1-0\": \"`created_at`\",\n    \"2-0\": \"`updated_at`\",\n    \"3-0\": \"`revision`\",\n    \"4-0\": \"`owner`\",\n    \"5-0\": \"`group`\",\n    \"h-1\": \"Filtering\",\n    \"h-2\": \"Ordering\",\n    \"0-1\": \"<div style=\\\"color: green\\\">&#x2713;</div>\",\n    \"1-1\": \"<div style=\\\"color: green\\\">&#x2713;</div>\",\n    \"2-1\": \"<div style=\\\"color: green\\\">&#x2713;</div>\",\n    \"3-1\": \"<div style=\\\"color: green\\\">&#x2713;</div>\",\n    \"4-1\": \"<div style=\\\"color: green\\\">&#x2713;</div>\",\n    \"5-1\": \"<div style=\\\"color: green\\\">&#x2713;</div>\",\n    \"0-2\": \"<div style=\\\"color: green\\\">&#x2713;</div>\",\n    \"1-2\": \"<div style=\\\"color: green\\\">&#x2713;</div>\",\n    \"2-2\": \"<div style=\\\"color: green\\\">&#x2713;</div>\",\n    \"3-2\": \"<div style=\\\"color: red\\\">&#x2717;</div>\",\n    \"4-2\": \"<div style=\\\"color: red\\\">&#x2717;</div>\",\n    \"5-2\": \"<div style=\\\"color: red\\\">&#x2717;</div>\",\n    \"h-0\": \"Field\"\n  },\n  \"cols\": 3,\n  \"rows\": 6\n}\n[/block]\n\n[block:api-header]\n{\n  \"type\": \"basic\",\n  \"title\": \"Filtering Data Objects\"\n}\n[/block]\n\nIn general, you would add filtering to your request, if you wanted to get only the Data Objects that meet certain criteria. You can achieve that by adding extra parameters to your Data Object `GET` call:\n[block:code]\n{\n  \"codes\": [\n    {\n      \"code\": \"curl -X GET -G \\\\\\n-H \\\"X-API-KEY: API_KEY\\\" \\\\\\n-g \\\"https://api.syncano.io/v1.1/instances/INSTANCE_NAME/classes/books/objects/\\\" \\\\\\n-d 'query={\\\"created_at\\\":{\\\"_gt\\\":\\\"2015-02-23T12:00:00Z\\\"}}'\",\n      \"language\": \"curl\"\n    },\n    {\n      \"code\": \"var Syncano = require(\\\"syncano\\\");  // CommonJS\\nvar connection = Syncano({accountKey: \\\"ACCOUNT_KEY\\\"});\\nvar DataObject = connection.DataObject;\\n\\nvar list = {instanceName: \\\"INSTANCE_NAME\\\", className: \\\"CLASS_NAME\\\"};\\nvar filter = {\\\"created_at\\\":{\\\"_gt\\\":\\\"2015-02-23T12:00:00Z\\\"}};\\n\\nDataObject.please().list(list).filter(filter).then(callback);\",\n      \"language\": \"javascript\"\n    },\n    {\n      \"code\": \"import datetime\\nimport syncano\\nfrom syncano.models import Object\\n\\nsyncano.connect(api_key=\\\"API_KEY\\\")\\n\\ndate = datetime.datetime.strptime(\\\"2013-06-22 18:27:13.886665\\\",\\n                                  \\\"%Y-%m-%d %H:%M:%S.%f\\\")\\n# created_at is the property we are checking\\n# is greater than '__gt'\\nbooks = Object.please.list(\\n    instance_name=\\\"INSTANCE_NAME\\\",\\n    class_name=\\\"book\\\"\\n).filter(created_at__gt=date)\",\n      \"language\": \"python\"\n    },\n    {\n      \"code\": \"ResponseGetList<Book> responseList = Syncano.please(Book.class)\\n        .where().gt(Entity.FIELD_CREATED_AT, date).get();\",\n      \"language\": \"java\",\n      \"name\": \"Android\"\n    },\n    {\n      \"code\": \"SCPredicate *pirateBookPredicate = [SCPredicate whereKey::::at:::\\\"title\\\" isEqualToString:@\\\"Pirate ships\\\"];\\n[[Book please] giveMeDataObjectsWithPredicate:pirateBookPredicate parameters:nil completion:^(NSArray *books, NSError *error) {\\n   //error handling\\n}];\",\n      \"language\": \"objectivec\",\n      \"name\": \"Objective-C\"\n    },\n    {\n      \"code\": \"let pirateBookPredicate = SCPredicate.whereKey(\\\"title\\\", isEqualToString: \\\"Pirate ships\\\")\\nBook.please().giveMeDataObjectsWithPredicate(pirateBookPredicate, parameters: nil) { books, error in\\n   //error handling\\n}\",\n      \"language\": \"objectivec\",\n      \"name\": \"Swift\"\n    },\n    {\n      \"code\": \"//NOT AVAILABLE\",\n      \"language\": \"csharp\",\n      \"name\": \"Unity\"\n    }\n  ]\n}\n[/block]\nIn the example above, results will be filtered by the `created_at` field and they will be greater than (`_gt`) the given date.\n\nHere you can find all the possible filter options for different types of Data Object fields:\n[block:parameters]\n{\n  \"data\": {\n    \"h-0\": \"Name of the filter\",\n    \"h-1\": \"Description\",\n    \"h-2\": \"Example\",\n    \"0-0\": \"**_gt**\",\n    \"1-0\": \"**_gte**\",\n    \"2-0\": \"**_lt**\",\n    \"3-0\": \"**_lte**\",\n    \"4-0\": \"**_eq**\",\n    \"5-0\": \"**_neq**\",\n    \"6-0\": \"**_exists**\",\n    \"7-0\": \"**_in**\",\n    \"7-1\": \"**In a given list**\\n\\n- checking if value of the field is on the provided list\\n\\n(list can contain up to 128 values)\",\n    \"0-2\": \"```\\n{\\\"year\\\": {\\\"_gt\\\": 1998}}\\n```\\n```\\n{\\\"meeting_date\\\": {\\\"_gt\\\": \\\"2015-02-22T05:09:24Z\\\"}}\\n```\",\n    \"1-2\": \"```\\n{\\\"year\\\": {\\\"_gte\\\": 2000}}\\n```\",\n    \"0-1\": \"**Greater than**\\n\\n- checking if value is greater than provided\\n- for `string`, it compares the alphabetical ordering\",\n    \"1-1\": \"**Greater than or equal to**\\n\\n- checking if value is greater or equal than provided\\n- for `string`, it compares the alphabetical ordering\",\n    \"2-1\": \"**Less than**\\n\\n- checking if value is lower than provided\\n- for `string`, it compares the alphabetical ordering\",\n    \"3-1\": \"**Less than or equal to**\\n\\n- checking if value is lower or equal than provided\\n- for `string`, it compares the alphabetical ordering\",\n    \"4-1\": \"**Equal to**\\n\\n- checking if value is equal than provided\",\n    \"5-1\": \"**Not equal to**\\n\\n- checking if value different than provided\",\n    \"6-1\": \"**Exist**\\n\\n- checking if field is not empty\",\n    \"6-2\": \"```\\n{\\\"year\\\": {\\\"_exists\\\":true}}\\n```\\n```\\n{\\\"subtitle\\\":{\\\"_exists\\\":true}}\\n```\",\n    \"7-2\": \"```\\n{\\\"year\\\":{\\\"_in\\\":[2000, 2001, 2002]}}\\n```\",\n    \"5-2\": \"```\\n{\\\"year\\\":{\\\"_neq\\\":2001\\\"}}\\n```\\n```\\n{\\\"title\\\":{\\\"_neq\\\":\\\"The Old Man and the Sea\\\"}}\\n```\",\n    \"4-2\": \"```\\n{\\\"year\\\":{\\\"_eq\\\":2000}}\\n```\\n```\\n{\\\"title\\\": {\\\"_eq\\\":\\\"The Old Man and the Sea\\\"}}\\n```\\n```\\n{\\\"meeting_date\\\":{\\\"_eq\\\": \\\"2015-02-22T05:09:24Z\\\"}}\\n```\",\n    \"3-2\": \"```\\n{\\\"year\\\": {\\\"_gte\\\": 2000}}\\n```\",\n    \"2-2\": \"```\\n{\\\"price\\\": {\\\"_lt\\\": 2.25}}\\n```\",\n    \"h-3\": \"Suitable for\",\n    \"0-3\": \"`integer`, `float`, `string`, `datetime`\",\n    \"1-3\": \"`integer`, `float`, `string`, `datetime`\",\n    \"2-3\": \"`integer`, `float`, `string`, `datetime`\",\n    \"3-3\": \"`integer`, `float`, `string`, `datetime`\",\n    \"4-3\": \"`integer`, `float`, `boolean`, `string`, `datetime`\",\n    \"5-3\": \"`integer`, `float`, `boolean`, `string`, `datetime`\",\n    \"6-3\": \"`integer`, `float`, `boolean`, `string`, `datetime`\",\n    \"7-3\": \"`integer`, `float`, `boolean`, `string`, `datetime`\",\n    \"8-0\": \"**_nin**\",\n    \"8-1\": \"**Not in a given list**\\n\\n- checking if value of the field is on the provided list. If it is, it filters out matching objects\\n\\n(list can contain up to 128 values)\",\n    \"8-2\": \"```\\n{\\\"year\\\":{\\\"_nin\\\":[2000, 2001, 2002]}}\\n```\\nWill return objects where year doesn't have a value of 2000, 2001 or 2002\",\n    \"8-3\": \"`integer`, `float`, `boolean`, `string`, `datetime`\",\n    \"9-0\": \"**_contains**\",\n    \"9-1\": \"**Contains**\\n**String**\\nChecks if a string contains the given query.\\n\\n**Array**\\nIn case of an array, checks if all passed elements are present. Lookup is type and case sensitive.\\n\\n**Relation**\\nIn case of a relation, checks if all passed object IDs are present.\",\n    \"9-2\": \"String:\\n```\\n{\\\"title\\\": {\\\"_contains\\\":\\\"Man\\\"}}\\n```\\nArray:\\n```\\n{\\\"year\\\": {\\\"_contains\\\": [2000, 2001, 2002]}}\\n```\\nRelation:\\n```\\n{\\\"books\\\": {\\\"_contains\\\": [\\\"20\\\", \\\"34\\\", \\\"99\\\"]}}\\n```\",\n    \"9-3\": \"`string`, `array`, `relation`\"\n  },\n  \"cols\": 4,\n  \"rows\": 10\n}\n[/block]\nThere are also several filtering options available for `string` field types:\n\n\n[block:callout]\n{\n  \"type\": \"info\",\n  \"body\": \"All examples below assume that we will be searching for a book with a title \\\"The Old Man and the Sea\\\". All the queries would return a book with such title\"\n}\n[/block]\n\n[block:parameters]\n{\n  \"data\": {\n    \"h-0\": \"Name of the filter\",\n    \"h-1\": \"Description\",\n    \"h-2\": \"Example\",\n    \"0-0\": \"**_startswith**\",\n    \"1-0\": \"**_endswith**\",\n    \"2-0\": \"**_istartswith**\",\n    \"3-0\": \"**_iendswith**\",\n    \"4-0\": \"**_icontains**\",\n    \"5-0\": \"**_ieq**\",\n    \"0-1\": \"**Starts with**\\n\\nChecks if a string starts with the given query\",\n    \"1-1\": \"**Ends with**\\n\\nChecks if a string ends with the given query\",\n    \"2-1\": \"**Case insensitive starts with**\\n\\nChecks if a string starts with the given query while ignoring the case of the letters\",\n    \"3-1\": \"**Case insensitive ends with**\\n\\nChecks if a string ends with the given query while ignoring the case of the letters\",\n    \"4-1\": \"**Case insensitive contains**\\n\\nChecks if a string contains the given query while ignoring the case of the letters\",\n    \"5-1\": \"**Case insensitive equal to**\\n\\nChecks if a string is equal the given query while ignoring the case of the letters\",\n    \"0-2\": \"```\\n{\\\"title\\\": {\\\"_startswith\\\":\\\"The Old Man\\\"}}\\n```\",\n    \"1-2\": \"```\\n{\\\"title\\\": {\\\"_endswith\\\":\\\"the Sea\\\"}}\\n```\",\n    \"2-2\": \"```\\n{\\\"title\\\": {\\\"_istartswith\\\":\\\"ThE OLd m\\\"}}\\n```\",\n    \"3-2\": \"```\\n{\\\"title\\\": {\\\"_iendswith\\\":\\\"the SEA\\\"}}\\n```\",\n    \"4-2\": \"```\\n{\\\"title\\\": {\\\"_icontains\\\":\\\"OLD MaN\\\"}}\\n```\",\n    \"5-2\": \"```\\n{\\\"title\\\": {\\\"_ieq\\\":\\\"ThE OlD mAn anD thE SeA\\\"}}\\n```\"\n  },\n  \"cols\": 3,\n  \"rows\": 6\n}\n[/block]\n\n[block:callout]\n{\n  \"type\": \"info\",\n  \"title\": \"Filtering in Syncano Libraries\",\n  \"body\": \"Using one of the Syncano Libraries, filtering might look differently from what was described here. To learn how to filter using chosen library, please follow our quick start guides available [here](doc:syncano-libraries).\"\n}\n[/block]\n\n[block:api-header]\n{\n  \"type\": \"basic\",\n  \"title\": \"Examples of filtering Data Objects\"\n}\n[/block]\n1. [Introduction](#section-introduction)\n2. [Simple filter on one field](#section-simple-filter-on-one-field)\n3. [Complex filtering on one field](#section-complex-filtering-on-one-field)\n4. [Filtering on multiple fields](#section-filtering-on-multiple-fields)\n\n### Introduction\nBelow you'll find couple of Data Object filtering examples. The examples assume that you have a Data Class called `books` and that this Data Class has the following schema:\n[block:code]\n{\n  \"codes\": [\n    {\n      \"code\": \"{\\n    \\\"type\\\": \\\"string\\\", \\n    \\\"name\\\": \\\"string\\\"\\n}, \\n{\\n    \\\"order_index\\\": true, \\n    \\\"filter_index\\\": true, \\n    \\\"type\\\": \\\"integer\\\", \\n    \\\"name\\\": \\\"release_year\\\"\\n}, \\n{\\n    \\\"type\\\": \\\"float\\\", \\n    \\\"name\\\": \\\"float\\\"\\n}, \\n{\\n    \\\"type\\\": \\\"text\\\", \\n    \\\"name\\\": \\\"text\\\"\\n}, \\n{\\n    \\\"type\\\": \\\"text\\\", \\n    \\\"name\\\": \\\"text2\\\"\\n}, \\n{\\n    \\\"order_index\\\": true, \\n    \\\"filter_index\\\": true, \\n    \\\"type\\\": \\\"integer\\\", \\n    \\\"name\\\": \\\"pages\\\"\\n}, \\n{\\n    \\\"type\\\": \\\"file\\\", \\n    \\\"name\\\": \\\"file\\\"\\n}\",\n      \"language\": \"json\"\n    }\n  ]\n}\n[/block]\nIn this Data Class, there are two fields with indexes, book `release_year` and  number of `pages`.\n\nI've populated `books` Data Class with some Data Objects, so without filtering I would see all of them.\n[block:callout]\n{\n  \"type\": \"warning\",\n  \"title\": \"Examples use fields skipping for clarity.\",\n  \"body\": \"In the examples below I use fields skipping that shows only fields that I'm interested in. All examples would also work without it but there would be much more noise.\\n\\nYou can read more about fields skipping [here](http://docs.syncano.com/v0.1.1/docs/skipping-fields-in-api-endpoints)\"\n}\n[/block]\nI'll skip all the fields except `release_year`, `id` and `pages` fields. Let's try it out:\n[block:code]\n{\n  \"codes\": [\n    {\n      \"code\": \"curl -X GET -G \\\\\\n-H \\\"X-API-KEY: API_KEY\\\" \\\\\\n\\\"https://api.syncano.io/v1.1/instances/INSTANCE_NAME/classes/books/objects/\\\"\\\\\\n-d fields=release_year,id,pages\",\n      \"language\": \"curl\"\n    },\n    {\n      \"code\": \"var Syncano = require(\\\"syncano\\\");  // CommonJS\\nvar connection = Syncano({accountKey: \\\"ACCOUNT_KEY\\\"});\\nvar DataObject = connection.DataObject;\\n\\nvar list = {instanceName: \\\"INSTANCE_NAME\\\", className: \\\"CLASS_NAME\\\"};\\nvar fields = [\\\"release_year\\\", \\\"id\\\", \\\"pages\\\"];\\n\\nDataObject.please().list(list).fields(fields).then(callback);\",\n      \"language\": \"javascript\"\n    },\n    {\n      \"code\": \"[Book.please giveMeDataObjectsWithParameters:@{ \\n    SCPleaseParameterFields : @[@\\\"release_year\\\", @\\\"id\\\", @\\\"pages\\\"] \\n} completion:^(NSArray *books, NSError *error) {\\n        //handle error\\n}];\",\n      \"language\": \"objectivec\",\n      \"name\": \"Objective-C\"\n    },\n    {\n      \"code\": \"Book.please().giveMeDataObjectsWithParameters([SCPleaseParameterFields:[\\\"release_year\\\", \\\"id\\\", \\\"pages\\\"]]) \\n{ books, error in\\n    //handle error\\n}\",\n      \"language\": \"objectivec\",\n      \"name\": \"Swift\"\n    },\n    {\n      \"code\": \"ResponseGetList<Book> responseSkip = Syncano.please(Book.class)\\n        .selectFields(FilterType.INCLUDE_FIELDS, \\\"release_year\\\", \\\"id\\\", \\\"pages\\\").get();\",\n      \"language\": \"java\",\n      \"name\": \"Android\"\n    },\n    {\n      \"code\": \"// NOT AVAILABLE\",\n      \"language\": \"csharp\",\n      \"name\": \"Unity\"\n    }\n  ]\n}\n[/block]\nOk, here is the response:\n[block:code]\n{\n  \"codes\": [\n    {\n      \"code\": \"{\\n    \\\"next\\\": null, \\n    \\\"prev\\\": null, \\n    \\\"objects\\\": [\\n        {\\n            \\\"id\\\": 642, \\n            \\\"release_year\\\": 1985, \\n            \\\"pages\\\": 200\\n        }, \\n        {\\n            \\\"id\\\": 643, \\n            \\\"release_year\\\": 1735, \\n            \\\"pages\\\": null\\n        }, \\n        {\\n            \\\"id\\\": 644, \\n            \\\"release_year\\\": 1999, \\n            \\\"pages\\\": null\\n        }, \\n        {\\n            \\\"id\\\": 2134, \\n            \\\"release_year\\\": 2010, \\n            \\\"pages\\\": 666\\n        }, \\n        {\\n            \\\"id\\\": 2135, \\n            \\\"release_year\\\": 650, \\n            \\\"pages\\\": 672\\n        }, \\n        {\\n            \\\"id\\\": 2136, \\n            \\\"release_year\\\": 1223, \\n            \\\"pages\\\": 110\\n        }\\n    ]\\n}\",\n      \"language\": \"json\"\n    }\n  ]\n}\n[/block]\nI created the `pages` field later, so some of the Data Objects have null as the value for the `pages` field.\n\n### Simple filter on one field\n\nWe will start from a simple query on `release_year`. We want to filter Data Objects that have a value of `release_year` greater than 1900. To achieve that, we only have to add a *query* param to the URL:\n[block:code]\n{\n  \"codes\": [\n    {\n      \"code\": \"curl -X GET -G \\\\\\n-H \\\"X-API-KEY: API_KEY\\\" \\\\\\n\\\"https://api.syncano.io/v1.1/instances/INSTANCE_NAME/classes/books/objects/\\\"\\\\\\n-d fields=release_year,id,pages \\\\\\n-d query={\\\"release_year\\\":{\\\"_gt\\\":1900}}\",\n      \"language\": \"curl\"\n    },\n    {\n      \"code\": \"var Syncano = require(\\\"syncano\\\");  // CommonJS\\nvar connection = Syncano({accountKey: \\\"ACCOUNT_KEY\\\"});\\nvar DataObject = connection.DataObject;\\n\\nvar filter = {\\\"release_year\\\":{\\\"_gt\\\":1900}};\\nvar list = {instanceName: \\\"INSTANCE_NAME\\\", className: \\\"CLASS_NAME\\\"};\\nvar fields = [\\\"release_year\\\", \\\"id\\\", \\\"pages\\\"];\\n\\nDataObject.please()\\n  .list(list)\\n\\t.filter(filter)\\n  .fields(fields)\\n  .then(callback);\",\n      \"language\": \"javascript\"\n    },\n    {\n      \"code\": \"import syncano\\nfrom syncano.models import Object\\n\\nsyncano.connect(api_key=\\\"API_KEY\\\")\\n\\nObject.please.list(\\n    instance_name=\\\"INSTANCE_NAME\\\",\\n    class_name=\\\"CLASS_NAME\\\"\\n).filter(release_year__gt=1900)\",\n      \"language\": \"python\"\n    },\n    {\n      \"code\": \"ResponseGetList<Book> responseSimple = Syncano.please(Book.class).where().gt(\\\"release_year\\\", 1900).get();\",\n      \"language\": \"java\",\n      \"name\": \"Android\"\n    },\n    {\n      \"code\": \"SCPredicate *bookPredicate = [SCPredicate whereKey:@\\\"release_year\\\" isGreaterThanNumber:@1990];\\n[[Book please] giveMeDataObjectsWithPredicate:bookPredicate parameters:nil completion:^(NSArray *books, NSError *error) {\\n        //error handling\\n}];\",\n      \"language\": \"objectivec\",\n      \"name\": \"Objective-C\"\n    },\n    {\n      \"code\": \"let bookPredicate = SCPredicate.whereKey(\\\"release_year\\\", isGreaterThanNumber: 1990)\\nBook.please().giveMeDataObjectsWithPredicate(bookPredicate, parameters: nil) { books, error in\\n    //error handling\\n}\",\n      \"language\": \"objectivec\",\n      \"name\": \"Swift\"\n    },\n    {\n      \"code\": \"// NOT AVAILABLE\",\n      \"language\": \"csharp\",\n      \"name\": \"Unity\"\n    }\n  ]\n}\n[/block]\nWe can see that Data Objects with ids 643, 2135 and 2136 disappeared, because they had a smaller `release_year` value. \n[block:code]\n{\n  \"codes\": [\n    {\n      \"code\": \"{\\n    \\\"next\\\": null, \\n    \\\"prev\\\": null, \\n    \\\"objects\\\": [\\n        {\\n            \\\"id\\\": 642, \\n            \\\"release_year\\\": 1985, \\n            \\\"pages\\\": 200\\n        }, \\n        {\\n            \\\"id\\\": 644, \\n            \\\"release_year\\\": 1999, \\n            \\\"pages\\\": null\\n        }, \\n        {\\n            \\\"id\\\": 2134, \\n            \\\"release_year\\\": 2010, \\n            \\\"pages\\\": 666\\n        }\\n    ]\\n}\",\n      \"language\": \"json\"\n    }\n  ]\n}\n[/block]\n\n### Complex filtering on one field\n\nWe can apply multiple filters to one field by adding another key-value pair to the query dictionary.\n[block:code]\n{\n  \"codes\": [\n    {\n      \"code\": \"curl -X GET -G \\\\\\n-H \\\"X-API-KEY: API_KEY\\\" \\\\\\n\\\"https://api.syncano.io/v1.1/instances/INSTANCE_NAME/classes/books/objects/\\\"\\\\\\n-d fields=release_year,id,pages \\\\\\n-d query={\\\"release_year\\\":{\\\"_gt\\\":1900,\\\"_lte\\\":2000}}\",\n      \"language\": \"curl\"\n    },\n    {\n      \"code\": \"var Syncano = require(\\\"syncano\\\");  // CommonJS\\nvar connection = Syncano({accountKey: \\\"ACCOUNT_KEY\\\"});\\nvar DataObject = connection.DataObject;\\n\\nvar filter = {\\\"_gt\\\":1900,\\\"_lte\\\":2000}};\\nvar list = {instanceName: \\\"INSTANCE_NAME\\\", className: \\\"CLASS_NAME\\\"};\\nvar fields = [\\\"release_year\\\", \\\"id\\\", \\\"pages\\\"];\\n\\nDataObject.please()\\n  .list(list)\\n\\t.filter(filter)\\n  .fields(fields)\\n  .then(callback);\",\n      \"language\": \"javascript\"\n    },\n    {\n      \"code\": \"import syncano\\nfrom syncano.models.base import Object\\n\\nsyncano.connect(api_key=\\\"API_KEY\\\")\\n\\nObject.please.list(\\n    instance_name=\\\"INSTANCE_NAME\\\",\\n    class_name=\\\"CLASS_NAME\\\"\\n).filter(\\n    release_year__gt=1900,\\n    release_year__lte=2000\\n)\",\n      \"language\": \"python\"\n    },\n    {\n      \"code\": \"ResponseGetList<Book> responseComplex = Syncano.please(Book.class)\\n        .selectFields(FilterType.INCLUDE_FIELDS, \\\"release_year\\\", \\\"id\\\", \\\"pages\\\")\\n        .where().gt(\\\"release_year\\\", 1900).lte(\\\"release_year\\\", 2000).get();\",\n      \"language\": \"java\",\n      \"name\": \"Android\"\n    },\n    {\n      \"code\": \"SCPredicate *bookPredicate1990 = [SCPredicate whereKey:@\\\"release_year\\\" isGreaterThanNumber:@1990];\\nSCPredicate *bookPredicate2000 = [SCPredicate whereKey:@\\\"release_year\\\" isLessThanOrEqualToNumber:@2000];\\nSCCompoundPredicate *predicate = [SCCompoundPredicate compoundPredicateWithPredicates:@[bookPredicate1990,bookPredicate2000]];\\n[[Book please] giveMeDataObjectsWithPredicate:predicate parameters:nil completion:^(NSArray *books, NSError *error) {\\n        //error handling\\n}];\",\n      \"language\": \"objectivec\"\n    },\n    {\n      \"code\": \"let bookPredicate1990 = SCPredicate.whereKey(\\\"release_year\\\", isGreaterThanNumber: 1990)\\nlet bookPredicate2000 = SCPredicate.whereKey(\\\"release_year\\\", isLessThanOrEqualToNumber: 2000)\\nlet predicate = SCCompoundPredicate.compoundPredicateWithPredicates([bookPredicate1990,bookPredicate2000])\\nBook.please().giveMeDataObjectsWithPredicate(predicate, parameters: nil) { books, error in\\n    //error handling\\n}\",\n      \"language\": \"objectivec\",\n      \"name\": \"Swift\"\n    },\n    {\n      \"code\": \"// NOT AVAILABLE\",\n      \"language\": \"csharp\"\n    }\n  ]\n}\n[/block]\nIn this case we would get Data Objects with `release_year` values that are greater than 1900 and smaller or equal to 2000.\n[block:code]\n{\n  \"codes\": [\n    {\n      \"code\": \"{\\n    \\\"next\\\": null, \\n    \\\"prev\\\": null, \\n    \\\"objects\\\": [\\n        {\\n            \\\"id\\\": 642, \\n            \\\"release_year\\\": 1985, \\n            \\\"pages\\\": 200\\n        }, \\n        {\\n            \\\"id\\\": 644, \\n            \\\"release_year\\\": 1999, \\n            \\\"pages\\\": null\\n        }\\n    ]\\n}\",\n      \"language\": \"json\"\n    }\n  ]\n}\n[/block]\n### Filtering on multiple fields\n\nIt's also possible to do filtering on more than one field at once. Here is a query which is the same as the previous one but also has a second filter for the `pages` value.\n[block:code]\n{\n  \"codes\": [\n    {\n      \"code\": \"curl -X GET -G \\\\\\n-H \\\"X-API-KEY: API_KEY\\\" \\\\\\n\\\"https://api.syncano.io/v1.1/instances/INSTANCE_NAME/classes/books/objects/\\\"\\\\\\n-d fields=release_year,id,pages \\\\\\n-d query={\\\"release_year\\\":{\\\"_gt\\\":1900,\\\"_lte\\\":2000},\\\"pages\\\":{\\\"_gt\\\":199}}\",\n      \"language\": \"curl\"\n    },\n    {\n      \"code\": \"var Syncano = require(\\\"syncano\\\");  // CommonJS\\nvar connection = Syncano({accountKey: \\\"ACCOUNT_KEY\\\"});\\nvar DataObject = connection.DataObject;\\n\\nvar filter = {\\\"release_year\\\":{\\\"_gt\\\":1900,\\\"_lte\\\":2000},\\\"pages\\\":{\\\"_gt\\\":199}};\\nvar list = {instanceName: \\\"INSTANCE_NAME\\\", className: \\\"CLASS_NAME\\\"};\\nvar fields = [\\\"release_year\\\", \\\"id\\\", \\\"pages\\\"];\\n\\nDataObject.please()\\n  .list(list)\\n\\t.filter(filter)\\n  .fields(fields)\\n  .then(callback);\",\n      \"language\": \"javascript\"\n    },\n    {\n      \"code\": \"import syncano\\nfrom syncano.models import Object\\n\\nsyncano.connect(api_key=\\\"API_KEY\\\")\\n\\nObject.please.list(\\n    instance_name=\\\"INSTANCE_NAME\\\",\\n    class_name=\\\"CLASS_NAME\\\"\\n).filter(\\n    release_year__gt=1900,\\n    release_year__lte=2000,\\n    pages__gt=199\\n)\",\n      \"language\": \"python\"\n    },\n    {\n      \"code\": \"ResponseGetList<Book> responseMultiple = Syncano.please(Book.class)\\n        .selectFields(FilterType.INCLUDE_FIELDS, \\\"release_year\\\", \\\"id\\\", \\\"pages\\\")\\n        .where().gt(\\\"release_year\\\", 1900).lte(\\\"release_year\\\", 2000).gt(\\\"pages\\\", 199).get();\",\n      \"language\": \"java\",\n      \"name\": \"Android\"\n    },\n    {\n      \"code\": \"SCPredicate *bookPredicate1990 = [SCPredicate whereKey:@\\\"release_year\\\" isGreaterThanNumber:@1990];\\nSCPredicate *bookPredicate2000 = [SCPredicate whereKey:@\\\"release_year\\\" isLessThanOrEqualToNumber:@2000];\\nSCPredicate *bookPredicatePages199 = [SCPredicate whereKey:@\\\"pages\\\" isGreaterThanNumber:@199];\\n\\nSCCompoundPredicate *predicate = [SCCompoundPredicate compoundPredicateWithPredicates:@[bookPredicate1990,bookPredicate2000,bookPredicatePages199]];\\n[[Book please] giveMeDataObjectsWithPredicate:predicate parameters:nil completion:^(NSArray *books, NSError *error) {\\n        //error handling\\n}];\",\n      \"language\": \"objectivec\"\n    },\n    {\n      \"code\": \"let bookPredicate1990 = SCPredicate.whereKey(\\\"release_year\\\", isGreaterThanNumber: 1990)\\nlet bookPredicate2000 = SCPredicate.whereKey(\\\"release_year\\\", isLessThanOrEqualToNumber: 2000)\\nlet bookPredicatePages199 = SCPredicate.whereKey(\\\"pages\\\", isGreaterThanNumber: 199)\\n\\nlet predicate = SCCompoundPredicate.compoundPredicateWithPredicates([bookPredicate1990,bookPredicate2000,bookPredicatePages199])\\nBook.please().giveMeDataObjectsWithPredicate(predicate, parameters: nil) { books, error in\\n    //error handling\\n}\",\n      \"language\": \"objectivec\",\n      \"name\": \"Swift\"\n    },\n    {\n      \"code\": \"// NOT AVAILABLE\",\n      \"language\": \"csharp\",\n      \"name\": \"Unity\"\n    }\n  ]\n}\n[/block]\nThis time, we're left with only one value! The `release_year` value that is greater than 1900 _and_ smaller than or equal to 2000 _and_ `pages` value is bigger than 199. \n[block:code]\n{\n  \"codes\": [\n    {\n      \"code\": \"{\\n    \\\"next\\\": null, \\n    \\\"prev\\\": null, \\n    \\\"objects\\\": [\\n        {\\n            \\\"id\\\": 642, \\n            \\\"release_year\\\": 1985, \\n            \\\"pages\\\": 200\\n        }\\n    ]\\n}\",\n      \"language\": \"json\"\n    }\n  ]\n}\n[/block]\n\n[block:api-header]\n{\n  \"type\": \"basic\",\n  \"title\": \"Ordering Data Objects\"\n}\n[/block]\nApart from limiting the response by using filtering, you can also request that the Data Objects to be ordered the way you want. To do that you should add an `order_by` parameter to the `GET` requests that you make. Assuming that you have an `order_index` set to `true` for `release_year` field, this is how such a call will look like:\n[block:code]\n{\n  \"codes\": [\n    {\n      \"code\": \"curl -X GET -G \\\\\\n-H \\\"X-API-KEY: API_KEY\\\" \\\\\\n-g \\\"https://api.syncano.io/v1.1/instances/INSTANCE_NAME/classes/books/objects/\\\" \\\\\\n-d order_by=release_year\",\n      \"language\": \"curl\"\n    },\n    {\n      \"code\": \"var Syncano = require(\\\"syncano\\\");  // CommonJS\\nvar connection = Syncano({accountKey: \\\"ACCOUNT_KEY\\\"});\\nvar DataObject = connection.DataObject;\\n\\nvar list = {instanceName: \\\"INSTANCE_NAME\\\", className: \\\"CLASS_NAME\\\"};\\nvar orderBy = \\\"release_year\\\";\\n\\nDataObject.please()\\n  .list(list)\\n\\t.orderBy(orderBy)\\n  .then(callback);\",\n      \"language\": \"javascript\"\n    },\n    {\n      \"code\": \"import syncano\\nfrom syncano.models import Object\\n\\nsyncano.connect(api_key=\\\"API_KEY\\\")\\n\\nObject.please.list(\\n    instance_name=\\\"INSTANCE_NAME\\\",\\n    class_name=\\\"CLASS_NAME\\\"\\n).order_by(\\n    'pages'\\n)\",\n      \"language\": \"python\"\n    },\n    {\n      \"code\": \"ResponseGetList<Book> responseOrdered = Syncano.please(Book.class)\\n        .orderBy(\\\"release_year\\\").get();\",\n      \"language\": \"java\",\n      \"name\": \"Android\"\n    },\n    {\n      \"code\": \"[Book.please giveMeDataObjectsWithParameters:@{\\n    SCPleaseParameterOrderBy : @\\\"release_year\\\" \\n} completion:^(NSArray *books, NSError *error) {\\n     //handle error\\n}];\",\n      \"language\": \"objectivec\"\n    },\n    {\n      \"code\": \"Book.please().giveMeDataObjectsWithParameters(\\n    [SCPleaseParameterOrderBy:\\\"release_year\\\"]) { books, error in\\n    //handle error\\n}\",\n      \"language\": \"objectivec\",\n      \"name\": \"Swift\"\n    },\n    {\n      \"code\": \"// NOT AVAILABLE\",\n      \"language\": \"csharp\",\n      \"name\": \"Unity\"\n    }\n  ]\n}\n[/block]\nThe default direction is ascending. If you want to reverse direction of ordering, add a minus sign to the field name:\n[block:code]\n{\n  \"codes\": [\n    {\n      \"code\": \"curl -X GET -G \\\\\\n-H \\\"X-API-KEY: API_KEY\\\" \\\\\\n-g \\\"https://api.syncano.io/v1.1/instances/INSTANCE_NAME/classes/books/objects/\\\" \\\\\\n-d order_by=-release_year\",\n      \"language\": \"curl\"\n    },\n    {\n      \"code\": \"var Syncano = require(\\\"syncano\\\");  // CommonJS\\nvar connection = Syncano({accountKey: \\\"ACCOUNT_KEY\\\"});\\nvar DataObject = connection.DataObject;\\n\\nvar list = {instanceName: \\\"INSTANCE_NAME\\\", className: \\\"CLASS_NAME\\\"};\\nvar orderBy = \\\"-release_year\\\";\\n\\nDataObject.please()\\n  .list(list)\\n\\t.orderBy(orderBy)\\n  .then(callback);\",\n      \"language\": \"javascript\"\n    },\n    {\n      \"code\": \"import syncano\\nfrom syncano.models import Object\\n\\nsyncano.connect(api_key=\\\"API_KEY\\\")\\n\\nObject.please.list(\\n    instance_name=\\\"INSTANCE_NAME\\\",\\n    class_name=\\\"CLASS_NAME\\\"\\n).order_by(\\n    '-pages'\\n)\",\n      \"language\": \"python\"\n    },\n    {\n      \"code\": \"ResponseGetList<Book> responseOrderedReversed = Syncano.please(Book.class)\\n        .orderBy(\\\"release_year\\\", SortOrder.DESCENDING).get();\",\n      \"language\": \"java\",\n      \"name\": \"Android\"\n    },\n    {\n      \"code\": \"[Book.please giveMeDataObjectsWithParameters:@{\\n    SCPleaseParameterOrderBy : @\\\"-release_year\\\" \\n} completion:^(NSArray *books, NSError *error) {\\n     //handle error\\n}];\",\n      \"language\": \"objectivec\"\n    },\n    {\n      \"code\": \"Book.please().giveMeDataObjectsWithParameters(\\n    [SCPleaseParameterOrderBy:\\\"-release_year\\\"]) { books, error in\\n    //handle error\\n}\",\n      \"language\": \"objectivec\",\n      \"name\": \"Swift\"\n    },\n    {\n      \"code\": \"// NOT AVAILABLE\",\n      \"language\": \"csharp\",\n      \"name\": \"Unity\"\n    }\n  ]\n}\n[/block]\nIf you try to order by an attribute that doesn't exist, you will get an error message:\n\n[block:code]\n{\n  \"codes\": [\n    {\n      \"code\": \"{ \\\"detail\\\": \\\"Incorrect order_by parameter provided.\\\" }\",\n      \"language\": \"json\"\n    }\n  ]\n}\n[/block]\nOrdering works with filtering. Just add another query parameter to the request:\n[block:code]\n{\n  \"codes\": [\n    {\n      \"code\": \"curl -X GET -G \\\\\\n-H \\\"X-API-KEY: API_KEY\\\" \\\\\\n\\\"https://api.syncano.io/v1.1/instances/my_instance/classes/books/objects/\\\" \\\\\\n-d -g query={\\\"release_year\\\":{\\\"_gt\\\":1900}} \\\\\\n-d fields=release_year,id,pages \\\\\\n-d order_by=release_year\",\n      \"language\": \"curl\"\n    },\n    {\n      \"code\": \"var Syncano = require(\\\"syncano\\\");  // CommonJS\\nvar connection = Syncano({accountKey: \\\"ACCOUNT_KEY\\\"});\\nvar DataObject = connection.DataObject;\\n\\nvar list = {instanceName: \\\"INSTANCE_NAME\\\", className: \\\"CLASS_NAME\\\"};\\nvar filter = {\\\"release_year\\\":{\\\"_gt\\\":1900}};\\nvar fields = [\\\"release_year\\\", \\\"id\\\", \\\"pages\\\"];\\nvar orderBy = \\\"-release_year\\\";\\n\\nDataObject.please()\\n  .list(list)\\n\\t.filter(filter)\\n\\t.fields(fields)\\n\\t.orderBy(orderBy)\\n  .then(callback);\",\n      \"language\": \"javascript\"\n    },\n    {\n      \"code\": \"import syncano\\nfrom syncano.models import Object\\n\\nsyncano.connect(api_key=\\\"API_KEY\\\")\\n\\nObject.please.list(\\n    instance_name=\\\"INSTANCE_NAME\\\",\\n    class_name=\\\"CLASS_NAME\\\"\\n).filter(\\n    release_year__gt=1900,\\n    release_year__lte=2000,\\n    pages__gt=199\\n).order_by(\\n    'pages'\\n)\",\n      \"language\": \"python\"\n    },\n    {\n      \"code\": \"ResponseGetList<Book> responseOrderedFiltered = Syncano.please(Book.class)\\n        .selectFields(FilterType.INCLUDE_FIELDS, \\\"release_year\\\", \\\"id\\\", \\\"pages\\\")\\n        .orderBy(\\\"release_year\\\").where().gt(\\\"release_year\\\", 1990).get();\",\n      \"language\": \"java\",\n      \"name\": \"Android\"\n    },\n    {\n      \"code\": \"SCPredicate *bookPredicate1990 = [SCPredicate whereKey:@\\\"release_year\\\" isGreaterThanNumber:@1990];\\n[Book.please giveMeDataObjectsWithPredicate:bookPredicate1990 parameters:@{\\n    SCPleaseParameterOrderBy : @\\\"release_year\\\" \\n} completion:^(NSArray *books, NSError *error) {\\n     //handle error\\n}];\",\n      \"language\": \"objectivec\"\n    },\n    {\n      \"code\": \"let bookPredicate1990 = SCPredicate.whereKey(\\\"release_year\\\", isGreaterThanNumber: 1990)\\n \\nBook.please().giveMeDataObjectsWithPredicate(bookPredicate1990, parameters:[SCPleaseParameterOrderBy:\\\"release_year\\\"]) { books, error in\\n    //handle error\\n}\",\n      \"language\": \"objectivec\",\n      \"name\": \"Swift\"\n    },\n    {\n      \"code\": \"// NOT AVAILABLE\",\n      \"language\": \"csharp\"\n    }\n  ]\n}\n[/block]\nResult will be filtered to Data Objects that have `release_year` values greater than 1900 and will be sorted in a ascending order:\n[block:code]\n{\n  \"codes\": [\n    {\n      \"code\": \"{\\n    \\\"next\\\": null, \\n    \\\"prev\\\": null, \\n    \\\"objects\\\": [\\n        {\\n            \\\"id\\\": 2134, \\n            \\\"release_year\\\": 2010, \\n            \\\"pages\\\": 666\\n        }, \\n        {\\n            \\\"id\\\": 644, \\n            \\\"release_year\\\": 1999, \\n            \\\"pages\\\": null\\n        },\\n        {\\n            \\\"id\\\": 642, \\n            \\\"release_year\\\": 1985, \\n            \\\"pages\\\": 200\\n        }\\n    ]\\n}\",\n      \"language\": \"json\"\n    }\n  ]\n}\n[/block]\n\n[block:api-header]\n{\n  \"type\": \"basic\",\n  \"title\": \"Using paging with filtering and ordering\"\n}\n[/block]\nIt works as you would expect, you can combine it:\n[block:code]\n{\n  \"codes\": [\n    {\n      \"code\": \"curl -X GET -G \\\\\\n-H \\\"X-API-KEY: API_KEY\\\" \\\\\\n\\\"https://api.syncano.io/v1.1/instances/INSTANCE_NAME/classes/books/objects/\\\" \\\\\\n-d -g query={\\\"release_year\\\":{\\\"_gt\\\":1900,\\\"_lte\\\":2000},\\\"pages\\\":{\\\"_gt\\\":199}} \\\\\\n-d fields=release_year,id,pages \\\\\\n-d page_size=1\",\n      \"language\": \"curl\"\n    },\n    {\n      \"code\": \"var Syncano = require(\\\"syncano\\\");  // CommonJS\\nvar connection = Syncano({accountKey: \\\"ACCOUNT_KEY\\\"});\\nvar DataObject = connection.DataObject;\\n\\nvar list = {instanceName: \\\"INSTANCE_NAME\\\", className: \\\"CLASS_NAME\\\"};\\nvar fields = [\\\"release_year\\\", \\\"id\\\", \\\"pages\\\"];\\nvar pageSize = 1;\\n\\nDataObject.please()\\n  .list(list)\\n\\t.fields(fields)\\n\\t.pageSize(pageSize)\\n  .then(callback);\",\n      \"language\": \"javascript\"\n    }\n  ]\n}\n[/block]\nThe API will automatically create pages with size equal to `page_size` for you and provide a link to the next page.\n[block:code]\n{\n  \"codes\": [\n    {\n      \"code\": \"{\\n    \\\"next\\\": \\\"/v1.1/instances/syncano/classes/books/objects/?direction=1&last_pk=2134&page_size=1&query=%7B%22release_year%22%3A%7B%22_gt%22%3A2%2C%22_lte%22%3A163%7D%2C%22pages%22%3A%7B%22_gt%22%3A12%7D%7D\\\", \\n    \\\"prev\\\": null, \\n    \\\"objects\\\": [\\n        {\\n            \\\"id\\\": 642, \\n            \\\"release_year\\\": 1985, \\n            \\\"pages\\\": 200\\n        }\\n    ]\\n}\",\n      \"language\": \"json\"\n    }\n  ]\n}\n[/block]\nMore info about paging can be found [here](http://docs.syncano.com/v0.1/docs/general-information#paging).\n[block:api-header]\n{\n  \"type\": \"basic\",\n  \"title\": \"Summary\"\n}\n[/block]\nIn this chapter you have learned how to use filtering and ordering when making Data Object requests to Syncano. You have also learned how to combine the ordering and filtering queries and use paging on the top of that.\n\nGo to [Incrementing / decrementing fields](doc:incrementing-decrementing-fields) chapter to learn more about Data Objects and their properties.","excerpt":"In this chapter you'll learn:\n- How to filter Data Objects\n- How to order Data Objects\n- How to combine filtering and ordering with Data Objects pagination","slug":"data-objects-filtering-ordering","type":"basic","title":"Filtering & Ordering"}

Filtering & Ordering

In this chapter you'll learn: - How to filter Data Objects - How to order Data Objects - How to combine filtering and ordering with Data Objects pagination

Chapter Sections: 1. [Overview](#overview) 2. [Setting up indexing](#setting-up-indexing) 3. [Filtering Data Objects](#filtering-data-objects) 4. [Examples of filtering Data Objects](#examples-of-filtering-data-objects) 5. [Ordering Data Objects](#ordering-data-objects) 6. [Using paging with filtering and ordering](#using-paging-with-filtering-and-ordering) 7. [Summary](#summary) [block:api-header] { "type": "basic", "title": "Overview" } [/block] Once you have your data in place, you might want to get it from the Syncano Platform. To make things easier and more flexible we allow filtering and ordering of the Data Objects that you make `GET` requests on. [block:api-header] { "type": "basic", "title": "Setting up indexing" } [/block] To be able to perform filtering or ordering on Data Objects, you should first add appropriate indexes to the Data Class Schema. [block:callout] { "type": "warning", "body": "Without proper indexes added to the Data Objects fields in Data Class Schema, filtering or ordering will not work!" } [/block] As an example, we will use a data class named Book, with following fields: [block:code] { "codes": [ { "code": "Book {\n year : integer, //year it was published\n num_of_pages : integer, // number of pages\n title: string, //book title\n intro: text, //introduction to the book - requires longer text\n author: string, //name of the author\n category: string //category name\n}", "language": "json" } ] } [/block] If you wanted to filter and order on a `year` field (to e.g. get all books published after year 2010 and sort by year), you would have to have `order_index` and `filter_index` set to `true` in Data Class Schema: [block:image] { "images": [ { "image": [ "https://files.readme.io/7a1c702-Screen_Shot_2016-08-11_at_17.55.11.png", "Screen Shot 2016-08-11 at 17.55.11.png", 977, 949, "#f7f7f7" ] } ] } [/block] [block:code] { "codes": [ { "code": "{ \n \"name\": \"year\",\n \"type\": \"integer\", \n \"order_index\": true, \n \"filter_index\": true\n}", "language": "json" } ] } [/block] [block:callout] { "type": "info", "body": "You can read more about Data Class Schemas [here](doc:classes)." } [/block] ### Filtering and ordering of the default Data Object fields There are several default fields in a Data Object (the ones that you don't define in schema, but they are created for you). Some of these fields can be ordered and filtered but you don't have to add indexing to these fields. These are the operations that you can perform on the default Data Object fields: [block:parameters] { "data": { "0-0": "`id`", "1-0": "`created_at`", "2-0": "`updated_at`", "3-0": "`revision`", "4-0": "`owner`", "5-0": "`group`", "h-1": "Filtering", "h-2": "Ordering", "0-1": "<div style=\"color: green\">&#x2713;</div>", "1-1": "<div style=\"color: green\">&#x2713;</div>", "2-1": "<div style=\"color: green\">&#x2713;</div>", "3-1": "<div style=\"color: green\">&#x2713;</div>", "4-1": "<div style=\"color: green\">&#x2713;</div>", "5-1": "<div style=\"color: green\">&#x2713;</div>", "0-2": "<div style=\"color: green\">&#x2713;</div>", "1-2": "<div style=\"color: green\">&#x2713;</div>", "2-2": "<div style=\"color: green\">&#x2713;</div>", "3-2": "<div style=\"color: red\">&#x2717;</div>", "4-2": "<div style=\"color: red\">&#x2717;</div>", "5-2": "<div style=\"color: red\">&#x2717;</div>", "h-0": "Field" }, "cols": 3, "rows": 6 } [/block] [block:api-header] { "type": "basic", "title": "Filtering Data Objects" } [/block] In general, you would add filtering to your request, if you wanted to get only the Data Objects that meet certain criteria. You can achieve that by adding extra parameters to your Data Object `GET` call: [block:code] { "codes": [ { "code": "curl -X GET -G \\\n-H \"X-API-KEY: API_KEY\" \\\n-g \"https://api.syncano.io/v1.1/instances/INSTANCE_NAME/classes/books/objects/\" \\\n-d 'query={\"created_at\":{\"_gt\":\"2015-02-23T12:00:00Z\"}}'", "language": "curl" }, { "code": "var Syncano = require(\"syncano\"); // CommonJS\nvar connection = Syncano({accountKey: \"ACCOUNT_KEY\"});\nvar DataObject = connection.DataObject;\n\nvar list = {instanceName: \"INSTANCE_NAME\", className: \"CLASS_NAME\"};\nvar filter = {\"created_at\":{\"_gt\":\"2015-02-23T12:00:00Z\"}};\n\nDataObject.please().list(list).filter(filter).then(callback);", "language": "javascript" }, { "code": "import datetime\nimport syncano\nfrom syncano.models import Object\n\nsyncano.connect(api_key=\"API_KEY\")\n\ndate = datetime.datetime.strptime(\"2013-06-22 18:27:13.886665\",\n \"%Y-%m-%d %H:%M:%S.%f\")\n# created_at is the property we are checking\n# is greater than '__gt'\nbooks = Object.please.list(\n instance_name=\"INSTANCE_NAME\",\n class_name=\"book\"\n).filter(created_at__gt=date)", "language": "python" }, { "code": "ResponseGetList<Book> responseList = Syncano.please(Book.class)\n .where().gt(Entity.FIELD_CREATED_AT, date).get();", "language": "java", "name": "Android" }, { "code": "SCPredicate *pirateBookPredicate = [SCPredicate whereKey:@\"title\" isEqualToString:@\"Pirate ships\"];\n[[Book please] giveMeDataObjectsWithPredicate:pirateBookPredicate parameters:nil completion:^(NSArray *books, NSError *error) {\n //error handling\n}];", "language": "objectivec", "name": "Objective-C" }, { "code": "let pirateBookPredicate = SCPredicate.whereKey(\"title\", isEqualToString: \"Pirate ships\")\nBook.please().giveMeDataObjectsWithPredicate(pirateBookPredicate, parameters: nil) { books, error in\n //error handling\n}", "language": "objectivec", "name": "Swift" }, { "code": "//NOT AVAILABLE", "language": "csharp", "name": "Unity" } ] } [/block] In the example above, results will be filtered by the `created_at` field and they will be greater than (`_gt`) the given date. Here you can find all the possible filter options for different types of Data Object fields: [block:parameters] { "data": { "h-0": "Name of the filter", "h-1": "Description", "h-2": "Example", "0-0": "**_gt**", "1-0": "**_gte**", "2-0": "**_lt**", "3-0": "**_lte**", "4-0": "**_eq**", "5-0": "**_neq**", "6-0": "**_exists**", "7-0": "**_in**", "7-1": "**In a given list**\n\n- checking if value of the field is on the provided list\n\n(list can contain up to 128 values)", "0-2": "```\n{\"year\": {\"_gt\": 1998}}\n```\n```\n{\"meeting_date\": {\"_gt\": \"2015-02-22T05:09:24Z\"}}\n```", "1-2": "```\n{\"year\": {\"_gte\": 2000}}\n```", "0-1": "**Greater than**\n\n- checking if value is greater than provided\n- for `string`, it compares the alphabetical ordering", "1-1": "**Greater than or equal to**\n\n- checking if value is greater or equal than provided\n- for `string`, it compares the alphabetical ordering", "2-1": "**Less than**\n\n- checking if value is lower than provided\n- for `string`, it compares the alphabetical ordering", "3-1": "**Less than or equal to**\n\n- checking if value is lower or equal than provided\n- for `string`, it compares the alphabetical ordering", "4-1": "**Equal to**\n\n- checking if value is equal than provided", "5-1": "**Not equal to**\n\n- checking if value different than provided", "6-1": "**Exist**\n\n- checking if field is not empty", "6-2": "```\n{\"year\": {\"_exists\":true}}\n```\n```\n{\"subtitle\":{\"_exists\":true}}\n```", "7-2": "```\n{\"year\":{\"_in\":[2000, 2001, 2002]}}\n```", "5-2": "```\n{\"year\":{\"_neq\":2001\"}}\n```\n```\n{\"title\":{\"_neq\":\"The Old Man and the Sea\"}}\n```", "4-2": "```\n{\"year\":{\"_eq\":2000}}\n```\n```\n{\"title\": {\"_eq\":\"The Old Man and the Sea\"}}\n```\n```\n{\"meeting_date\":{\"_eq\": \"2015-02-22T05:09:24Z\"}}\n```", "3-2": "```\n{\"year\": {\"_gte\": 2000}}\n```", "2-2": "```\n{\"price\": {\"_lt\": 2.25}}\n```", "h-3": "Suitable for", "0-3": "`integer`, `float`, `string`, `datetime`", "1-3": "`integer`, `float`, `string`, `datetime`", "2-3": "`integer`, `float`, `string`, `datetime`", "3-3": "`integer`, `float`, `string`, `datetime`", "4-3": "`integer`, `float`, `boolean`, `string`, `datetime`", "5-3": "`integer`, `float`, `boolean`, `string`, `datetime`", "6-3": "`integer`, `float`, `boolean`, `string`, `datetime`", "7-3": "`integer`, `float`, `boolean`, `string`, `datetime`", "8-0": "**_nin**", "8-1": "**Not in a given list**\n\n- checking if value of the field is on the provided list. If it is, it filters out matching objects\n\n(list can contain up to 128 values)", "8-2": "```\n{\"year\":{\"_nin\":[2000, 2001, 2002]}}\n```\nWill return objects where year doesn't have a value of 2000, 2001 or 2002", "8-3": "`integer`, `float`, `boolean`, `string`, `datetime`", "9-0": "**_contains**", "9-1": "**Contains**\n**String**\nChecks if a string contains the given query.\n\n**Array**\nIn case of an array, checks if all passed elements are present. Lookup is type and case sensitive.\n\n**Relation**\nIn case of a relation, checks if all passed object IDs are present.", "9-2": "String:\n```\n{\"title\": {\"_contains\":\"Man\"}}\n```\nArray:\n```\n{\"year\": {\"_contains\": [2000, 2001, 2002]}}\n```\nRelation:\n```\n{\"books\": {\"_contains\": [\"20\", \"34\", \"99\"]}}\n```", "9-3": "`string`, `array`, `relation`" }, "cols": 4, "rows": 10 } [/block] There are also several filtering options available for `string` field types: [block:callout] { "type": "info", "body": "All examples below assume that we will be searching for a book with a title \"The Old Man and the Sea\". All the queries would return a book with such title" } [/block] [block:parameters] { "data": { "h-0": "Name of the filter", "h-1": "Description", "h-2": "Example", "0-0": "**_startswith**", "1-0": "**_endswith**", "2-0": "**_istartswith**", "3-0": "**_iendswith**", "4-0": "**_icontains**", "5-0": "**_ieq**", "0-1": "**Starts with**\n\nChecks if a string starts with the given query", "1-1": "**Ends with**\n\nChecks if a string ends with the given query", "2-1": "**Case insensitive starts with**\n\nChecks if a string starts with the given query while ignoring the case of the letters", "3-1": "**Case insensitive ends with**\n\nChecks if a string ends with the given query while ignoring the case of the letters", "4-1": "**Case insensitive contains**\n\nChecks if a string contains the given query while ignoring the case of the letters", "5-1": "**Case insensitive equal to**\n\nChecks if a string is equal the given query while ignoring the case of the letters", "0-2": "```\n{\"title\": {\"_startswith\":\"The Old Man\"}}\n```", "1-2": "```\n{\"title\": {\"_endswith\":\"the Sea\"}}\n```", "2-2": "```\n{\"title\": {\"_istartswith\":\"ThE OLd m\"}}\n```", "3-2": "```\n{\"title\": {\"_iendswith\":\"the SEA\"}}\n```", "4-2": "```\n{\"title\": {\"_icontains\":\"OLD MaN\"}}\n```", "5-2": "```\n{\"title\": {\"_ieq\":\"ThE OlD mAn anD thE SeA\"}}\n```" }, "cols": 3, "rows": 6 } [/block] [block:callout] { "type": "info", "title": "Filtering in Syncano Libraries", "body": "Using one of the Syncano Libraries, filtering might look differently from what was described here. To learn how to filter using chosen library, please follow our quick start guides available [here](doc:syncano-libraries)." } [/block] [block:api-header] { "type": "basic", "title": "Examples of filtering Data Objects" } [/block] 1. [Introduction](#section-introduction) 2. [Simple filter on one field](#section-simple-filter-on-one-field) 3. [Complex filtering on one field](#section-complex-filtering-on-one-field) 4. [Filtering on multiple fields](#section-filtering-on-multiple-fields) ### Introduction Below you'll find couple of Data Object filtering examples. The examples assume that you have a Data Class called `books` and that this Data Class has the following schema: [block:code] { "codes": [ { "code": "{\n \"type\": \"string\", \n \"name\": \"string\"\n}, \n{\n \"order_index\": true, \n \"filter_index\": true, \n \"type\": \"integer\", \n \"name\": \"release_year\"\n}, \n{\n \"type\": \"float\", \n \"name\": \"float\"\n}, \n{\n \"type\": \"text\", \n \"name\": \"text\"\n}, \n{\n \"type\": \"text\", \n \"name\": \"text2\"\n}, \n{\n \"order_index\": true, \n \"filter_index\": true, \n \"type\": \"integer\", \n \"name\": \"pages\"\n}, \n{\n \"type\": \"file\", \n \"name\": \"file\"\n}", "language": "json" } ] } [/block] In this Data Class, there are two fields with indexes, book `release_year` and number of `pages`. I've populated `books` Data Class with some Data Objects, so without filtering I would see all of them. [block:callout] { "type": "warning", "title": "Examples use fields skipping for clarity.", "body": "In the examples below I use fields skipping that shows only fields that I'm interested in. All examples would also work without it but there would be much more noise.\n\nYou can read more about fields skipping [here](http://docs.syncano.com/v0.1.1/docs/skipping-fields-in-api-endpoints)" } [/block] I'll skip all the fields except `release_year`, `id` and `pages` fields. Let's try it out: [block:code] { "codes": [ { "code": "curl -X GET -G \\\n-H \"X-API-KEY: API_KEY\" \\\n\"https://api.syncano.io/v1.1/instances/INSTANCE_NAME/classes/books/objects/\"\\\n-d fields=release_year,id,pages", "language": "curl" }, { "code": "var Syncano = require(\"syncano\"); // CommonJS\nvar connection = Syncano({accountKey: \"ACCOUNT_KEY\"});\nvar DataObject = connection.DataObject;\n\nvar list = {instanceName: \"INSTANCE_NAME\", className: \"CLASS_NAME\"};\nvar fields = [\"release_year\", \"id\", \"pages\"];\n\nDataObject.please().list(list).fields(fields).then(callback);", "language": "javascript" }, { "code": "[Book.please giveMeDataObjectsWithParameters:@{ \n SCPleaseParameterFields : @[@\"release_year\", @\"id\", @\"pages\"] \n} completion:^(NSArray *books, NSError *error) {\n //handle error\n}];", "language": "objectivec", "name": "Objective-C" }, { "code": "Book.please().giveMeDataObjectsWithParameters([SCPleaseParameterFields:[\"release_year\", \"id\", \"pages\"]]) \n{ books, error in\n //handle error\n}", "language": "objectivec", "name": "Swift" }, { "code": "ResponseGetList<Book> responseSkip = Syncano.please(Book.class)\n .selectFields(FilterType.INCLUDE_FIELDS, \"release_year\", \"id\", \"pages\").get();", "language": "java", "name": "Android" }, { "code": "// NOT AVAILABLE", "language": "csharp", "name": "Unity" } ] } [/block] Ok, here is the response: [block:code] { "codes": [ { "code": "{\n \"next\": null, \n \"prev\": null, \n \"objects\": [\n {\n \"id\": 642, \n \"release_year\": 1985, \n \"pages\": 200\n }, \n {\n \"id\": 643, \n \"release_year\": 1735, \n \"pages\": null\n }, \n {\n \"id\": 644, \n \"release_year\": 1999, \n \"pages\": null\n }, \n {\n \"id\": 2134, \n \"release_year\": 2010, \n \"pages\": 666\n }, \n {\n \"id\": 2135, \n \"release_year\": 650, \n \"pages\": 672\n }, \n {\n \"id\": 2136, \n \"release_year\": 1223, \n \"pages\": 110\n }\n ]\n}", "language": "json" } ] } [/block] I created the `pages` field later, so some of the Data Objects have null as the value for the `pages` field. ### Simple filter on one field We will start from a simple query on `release_year`. We want to filter Data Objects that have a value of `release_year` greater than 1900. To achieve that, we only have to add a *query* param to the URL: [block:code] { "codes": [ { "code": "curl -X GET -G \\\n-H \"X-API-KEY: API_KEY\" \\\n\"https://api.syncano.io/v1.1/instances/INSTANCE_NAME/classes/books/objects/\"\\\n-d fields=release_year,id,pages \\\n-d query={\"release_year\":{\"_gt\":1900}}", "language": "curl" }, { "code": "var Syncano = require(\"syncano\"); // CommonJS\nvar connection = Syncano({accountKey: \"ACCOUNT_KEY\"});\nvar DataObject = connection.DataObject;\n\nvar filter = {\"release_year\":{\"_gt\":1900}};\nvar list = {instanceName: \"INSTANCE_NAME\", className: \"CLASS_NAME\"};\nvar fields = [\"release_year\", \"id\", \"pages\"];\n\nDataObject.please()\n .list(list)\n\t.filter(filter)\n .fields(fields)\n .then(callback);", "language": "javascript" }, { "code": "import syncano\nfrom syncano.models import Object\n\nsyncano.connect(api_key=\"API_KEY\")\n\nObject.please.list(\n instance_name=\"INSTANCE_NAME\",\n class_name=\"CLASS_NAME\"\n).filter(release_year__gt=1900)", "language": "python" }, { "code": "ResponseGetList<Book> responseSimple = Syncano.please(Book.class).where().gt(\"release_year\", 1900).get();", "language": "java", "name": "Android" }, { "code": "SCPredicate *bookPredicate = [SCPredicate whereKey:@\"release_year\" isGreaterThanNumber:@1990];\n[[Book please] giveMeDataObjectsWithPredicate:bookPredicate parameters:nil completion:^(NSArray *books, NSError *error) {\n //error handling\n}];", "language": "objectivec", "name": "Objective-C" }, { "code": "let bookPredicate = SCPredicate.whereKey(\"release_year\", isGreaterThanNumber: 1990)\nBook.please().giveMeDataObjectsWithPredicate(bookPredicate, parameters: nil) { books, error in\n //error handling\n}", "language": "objectivec", "name": "Swift" }, { "code": "// NOT AVAILABLE", "language": "csharp", "name": "Unity" } ] } [/block] We can see that Data Objects with ids 643, 2135 and 2136 disappeared, because they had a smaller `release_year` value. [block:code] { "codes": [ { "code": "{\n \"next\": null, \n \"prev\": null, \n \"objects\": [\n {\n \"id\": 642, \n \"release_year\": 1985, \n \"pages\": 200\n }, \n {\n \"id\": 644, \n \"release_year\": 1999, \n \"pages\": null\n }, \n {\n \"id\": 2134, \n \"release_year\": 2010, \n \"pages\": 666\n }\n ]\n}", "language": "json" } ] } [/block] ### Complex filtering on one field We can apply multiple filters to one field by adding another key-value pair to the query dictionary. [block:code] { "codes": [ { "code": "curl -X GET -G \\\n-H \"X-API-KEY: API_KEY\" \\\n\"https://api.syncano.io/v1.1/instances/INSTANCE_NAME/classes/books/objects/\"\\\n-d fields=release_year,id,pages \\\n-d query={\"release_year\":{\"_gt\":1900,\"_lte\":2000}}", "language": "curl" }, { "code": "var Syncano = require(\"syncano\"); // CommonJS\nvar connection = Syncano({accountKey: \"ACCOUNT_KEY\"});\nvar DataObject = connection.DataObject;\n\nvar filter = {\"_gt\":1900,\"_lte\":2000}};\nvar list = {instanceName: \"INSTANCE_NAME\", className: \"CLASS_NAME\"};\nvar fields = [\"release_year\", \"id\", \"pages\"];\n\nDataObject.please()\n .list(list)\n\t.filter(filter)\n .fields(fields)\n .then(callback);", "language": "javascript" }, { "code": "import syncano\nfrom syncano.models.base import Object\n\nsyncano.connect(api_key=\"API_KEY\")\n\nObject.please.list(\n instance_name=\"INSTANCE_NAME\",\n class_name=\"CLASS_NAME\"\n).filter(\n release_year__gt=1900,\n release_year__lte=2000\n)", "language": "python" }, { "code": "ResponseGetList<Book> responseComplex = Syncano.please(Book.class)\n .selectFields(FilterType.INCLUDE_FIELDS, \"release_year\", \"id\", \"pages\")\n .where().gt(\"release_year\", 1900).lte(\"release_year\", 2000).get();", "language": "java", "name": "Android" }, { "code": "SCPredicate *bookPredicate1990 = [SCPredicate whereKey:@\"release_year\" isGreaterThanNumber:@1990];\nSCPredicate *bookPredicate2000 = [SCPredicate whereKey:@\"release_year\" isLessThanOrEqualToNumber:@2000];\nSCCompoundPredicate *predicate = [SCCompoundPredicate compoundPredicateWithPredicates:@[bookPredicate1990,bookPredicate2000]];\n[[Book please] giveMeDataObjectsWithPredicate:predicate parameters:nil completion:^(NSArray *books, NSError *error) {\n //error handling\n}];", "language": "objectivec" }, { "code": "let bookPredicate1990 = SCPredicate.whereKey(\"release_year\", isGreaterThanNumber: 1990)\nlet bookPredicate2000 = SCPredicate.whereKey(\"release_year\", isLessThanOrEqualToNumber: 2000)\nlet predicate = SCCompoundPredicate.compoundPredicateWithPredicates([bookPredicate1990,bookPredicate2000])\nBook.please().giveMeDataObjectsWithPredicate(predicate, parameters: nil) { books, error in\n //error handling\n}", "language": "objectivec", "name": "Swift" }, { "code": "// NOT AVAILABLE", "language": "csharp" } ] } [/block] In this case we would get Data Objects with `release_year` values that are greater than 1900 and smaller or equal to 2000. [block:code] { "codes": [ { "code": "{\n \"next\": null, \n \"prev\": null, \n \"objects\": [\n {\n \"id\": 642, \n \"release_year\": 1985, \n \"pages\": 200\n }, \n {\n \"id\": 644, \n \"release_year\": 1999, \n \"pages\": null\n }\n ]\n}", "language": "json" } ] } [/block] ### Filtering on multiple fields It's also possible to do filtering on more than one field at once. Here is a query which is the same as the previous one but also has a second filter for the `pages` value. [block:code] { "codes": [ { "code": "curl -X GET -G \\\n-H \"X-API-KEY: API_KEY\" \\\n\"https://api.syncano.io/v1.1/instances/INSTANCE_NAME/classes/books/objects/\"\\\n-d fields=release_year,id,pages \\\n-d query={\"release_year\":{\"_gt\":1900,\"_lte\":2000},\"pages\":{\"_gt\":199}}", "language": "curl" }, { "code": "var Syncano = require(\"syncano\"); // CommonJS\nvar connection = Syncano({accountKey: \"ACCOUNT_KEY\"});\nvar DataObject = connection.DataObject;\n\nvar filter = {\"release_year\":{\"_gt\":1900,\"_lte\":2000},\"pages\":{\"_gt\":199}};\nvar list = {instanceName: \"INSTANCE_NAME\", className: \"CLASS_NAME\"};\nvar fields = [\"release_year\", \"id\", \"pages\"];\n\nDataObject.please()\n .list(list)\n\t.filter(filter)\n .fields(fields)\n .then(callback);", "language": "javascript" }, { "code": "import syncano\nfrom syncano.models import Object\n\nsyncano.connect(api_key=\"API_KEY\")\n\nObject.please.list(\n instance_name=\"INSTANCE_NAME\",\n class_name=\"CLASS_NAME\"\n).filter(\n release_year__gt=1900,\n release_year__lte=2000,\n pages__gt=199\n)", "language": "python" }, { "code": "ResponseGetList<Book> responseMultiple = Syncano.please(Book.class)\n .selectFields(FilterType.INCLUDE_FIELDS, \"release_year\", \"id\", \"pages\")\n .where().gt(\"release_year\", 1900).lte(\"release_year\", 2000).gt(\"pages\", 199).get();", "language": "java", "name": "Android" }, { "code": "SCPredicate *bookPredicate1990 = [SCPredicate whereKey:@\"release_year\" isGreaterThanNumber:@1990];\nSCPredicate *bookPredicate2000 = [SCPredicate whereKey:@\"release_year\" isLessThanOrEqualToNumber:@2000];\nSCPredicate *bookPredicatePages199 = [SCPredicate whereKey:@\"pages\" isGreaterThanNumber:@199];\n\nSCCompoundPredicate *predicate = [SCCompoundPredicate compoundPredicateWithPredicates:@[bookPredicate1990,bookPredicate2000,bookPredicatePages199]];\n[[Book please] giveMeDataObjectsWithPredicate:predicate parameters:nil completion:^(NSArray *books, NSError *error) {\n //error handling\n}];", "language": "objectivec" }, { "code": "let bookPredicate1990 = SCPredicate.whereKey(\"release_year\", isGreaterThanNumber: 1990)\nlet bookPredicate2000 = SCPredicate.whereKey(\"release_year\", isLessThanOrEqualToNumber: 2000)\nlet bookPredicatePages199 = SCPredicate.whereKey(\"pages\", isGreaterThanNumber: 199)\n\nlet predicate = SCCompoundPredicate.compoundPredicateWithPredicates([bookPredicate1990,bookPredicate2000,bookPredicatePages199])\nBook.please().giveMeDataObjectsWithPredicate(predicate, parameters: nil) { books, error in\n //error handling\n}", "language": "objectivec", "name": "Swift" }, { "code": "// NOT AVAILABLE", "language": "csharp", "name": "Unity" } ] } [/block] This time, we're left with only one value! The `release_year` value that is greater than 1900 _and_ smaller than or equal to 2000 _and_ `pages` value is bigger than 199. [block:code] { "codes": [ { "code": "{\n \"next\": null, \n \"prev\": null, \n \"objects\": [\n {\n \"id\": 642, \n \"release_year\": 1985, \n \"pages\": 200\n }\n ]\n}", "language": "json" } ] } [/block] [block:api-header] { "type": "basic", "title": "Ordering Data Objects" } [/block] Apart from limiting the response by using filtering, you can also request that the Data Objects to be ordered the way you want. To do that you should add an `order_by` parameter to the `GET` requests that you make. Assuming that you have an `order_index` set to `true` for `release_year` field, this is how such a call will look like: [block:code] { "codes": [ { "code": "curl -X GET -G \\\n-H \"X-API-KEY: API_KEY\" \\\n-g \"https://api.syncano.io/v1.1/instances/INSTANCE_NAME/classes/books/objects/\" \\\n-d order_by=release_year", "language": "curl" }, { "code": "var Syncano = require(\"syncano\"); // CommonJS\nvar connection = Syncano({accountKey: \"ACCOUNT_KEY\"});\nvar DataObject = connection.DataObject;\n\nvar list = {instanceName: \"INSTANCE_NAME\", className: \"CLASS_NAME\"};\nvar orderBy = \"release_year\";\n\nDataObject.please()\n .list(list)\n\t.orderBy(orderBy)\n .then(callback);", "language": "javascript" }, { "code": "import syncano\nfrom syncano.models import Object\n\nsyncano.connect(api_key=\"API_KEY\")\n\nObject.please.list(\n instance_name=\"INSTANCE_NAME\",\n class_name=\"CLASS_NAME\"\n).order_by(\n 'pages'\n)", "language": "python" }, { "code": "ResponseGetList<Book> responseOrdered = Syncano.please(Book.class)\n .orderBy(\"release_year\").get();", "language": "java", "name": "Android" }, { "code": "[Book.please giveMeDataObjectsWithParameters:@{\n SCPleaseParameterOrderBy : @\"release_year\" \n} completion:^(NSArray *books, NSError *error) {\n //handle error\n}];", "language": "objectivec" }, { "code": "Book.please().giveMeDataObjectsWithParameters(\n [SCPleaseParameterOrderBy:\"release_year\"]) { books, error in\n //handle error\n}", "language": "objectivec", "name": "Swift" }, { "code": "// NOT AVAILABLE", "language": "csharp", "name": "Unity" } ] } [/block] The default direction is ascending. If you want to reverse direction of ordering, add a minus sign to the field name: [block:code] { "codes": [ { "code": "curl -X GET -G \\\n-H \"X-API-KEY: API_KEY\" \\\n-g \"https://api.syncano.io/v1.1/instances/INSTANCE_NAME/classes/books/objects/\" \\\n-d order_by=-release_year", "language": "curl" }, { "code": "var Syncano = require(\"syncano\"); // CommonJS\nvar connection = Syncano({accountKey: \"ACCOUNT_KEY\"});\nvar DataObject = connection.DataObject;\n\nvar list = {instanceName: \"INSTANCE_NAME\", className: \"CLASS_NAME\"};\nvar orderBy = \"-release_year\";\n\nDataObject.please()\n .list(list)\n\t.orderBy(orderBy)\n .then(callback);", "language": "javascript" }, { "code": "import syncano\nfrom syncano.models import Object\n\nsyncano.connect(api_key=\"API_KEY\")\n\nObject.please.list(\n instance_name=\"INSTANCE_NAME\",\n class_name=\"CLASS_NAME\"\n).order_by(\n '-pages'\n)", "language": "python" }, { "code": "ResponseGetList<Book> responseOrderedReversed = Syncano.please(Book.class)\n .orderBy(\"release_year\", SortOrder.DESCENDING).get();", "language": "java", "name": "Android" }, { "code": "[Book.please giveMeDataObjectsWithParameters:@{\n SCPleaseParameterOrderBy : @\"-release_year\" \n} completion:^(NSArray *books, NSError *error) {\n //handle error\n}];", "language": "objectivec" }, { "code": "Book.please().giveMeDataObjectsWithParameters(\n [SCPleaseParameterOrderBy:\"-release_year\"]) { books, error in\n //handle error\n}", "language": "objectivec", "name": "Swift" }, { "code": "// NOT AVAILABLE", "language": "csharp", "name": "Unity" } ] } [/block] If you try to order by an attribute that doesn't exist, you will get an error message: [block:code] { "codes": [ { "code": "{ \"detail\": \"Incorrect order_by parameter provided.\" }", "language": "json" } ] } [/block] Ordering works with filtering. Just add another query parameter to the request: [block:code] { "codes": [ { "code": "curl -X GET -G \\\n-H \"X-API-KEY: API_KEY\" \\\n\"https://api.syncano.io/v1.1/instances/my_instance/classes/books/objects/\" \\\n-d -g query={\"release_year\":{\"_gt\":1900}} \\\n-d fields=release_year,id,pages \\\n-d order_by=release_year", "language": "curl" }, { "code": "var Syncano = require(\"syncano\"); // CommonJS\nvar connection = Syncano({accountKey: \"ACCOUNT_KEY\"});\nvar DataObject = connection.DataObject;\n\nvar list = {instanceName: \"INSTANCE_NAME\", className: \"CLASS_NAME\"};\nvar filter = {\"release_year\":{\"_gt\":1900}};\nvar fields = [\"release_year\", \"id\", \"pages\"];\nvar orderBy = \"-release_year\";\n\nDataObject.please()\n .list(list)\n\t.filter(filter)\n\t.fields(fields)\n\t.orderBy(orderBy)\n .then(callback);", "language": "javascript" }, { "code": "import syncano\nfrom syncano.models import Object\n\nsyncano.connect(api_key=\"API_KEY\")\n\nObject.please.list(\n instance_name=\"INSTANCE_NAME\",\n class_name=\"CLASS_NAME\"\n).filter(\n release_year__gt=1900,\n release_year__lte=2000,\n pages__gt=199\n).order_by(\n 'pages'\n)", "language": "python" }, { "code": "ResponseGetList<Book> responseOrderedFiltered = Syncano.please(Book.class)\n .selectFields(FilterType.INCLUDE_FIELDS, \"release_year\", \"id\", \"pages\")\n .orderBy(\"release_year\").where().gt(\"release_year\", 1990).get();", "language": "java", "name": "Android" }, { "code": "SCPredicate *bookPredicate1990 = [SCPredicate whereKey:@\"release_year\" isGreaterThanNumber:@1990];\n[Book.please giveMeDataObjectsWithPredicate:bookPredicate1990 parameters:@{\n SCPleaseParameterOrderBy : @\"release_year\" \n} completion:^(NSArray *books, NSError *error) {\n //handle error\n}];", "language": "objectivec" }, { "code": "let bookPredicate1990 = SCPredicate.whereKey(\"release_year\", isGreaterThanNumber: 1990)\n \nBook.please().giveMeDataObjectsWithPredicate(bookPredicate1990, parameters:[SCPleaseParameterOrderBy:\"release_year\"]) { books, error in\n //handle error\n}", "language": "objectivec", "name": "Swift" }, { "code": "// NOT AVAILABLE", "language": "csharp" } ] } [/block] Result will be filtered to Data Objects that have `release_year` values greater than 1900 and will be sorted in a ascending order: [block:code] { "codes": [ { "code": "{\n \"next\": null, \n \"prev\": null, \n \"objects\": [\n {\n \"id\": 2134, \n \"release_year\": 2010, \n \"pages\": 666\n }, \n {\n \"id\": 644, \n \"release_year\": 1999, \n \"pages\": null\n },\n {\n \"id\": 642, \n \"release_year\": 1985, \n \"pages\": 200\n }\n ]\n}", "language": "json" } ] } [/block] [block:api-header] { "type": "basic", "title": "Using paging with filtering and ordering" } [/block] It works as you would expect, you can combine it: [block:code] { "codes": [ { "code": "curl -X GET -G \\\n-H \"X-API-KEY: API_KEY\" \\\n\"https://api.syncano.io/v1.1/instances/INSTANCE_NAME/classes/books/objects/\" \\\n-d -g query={\"release_year\":{\"_gt\":1900,\"_lte\":2000},\"pages\":{\"_gt\":199}} \\\n-d fields=release_year,id,pages \\\n-d page_size=1", "language": "curl" }, { "code": "var Syncano = require(\"syncano\"); // CommonJS\nvar connection = Syncano({accountKey: \"ACCOUNT_KEY\"});\nvar DataObject = connection.DataObject;\n\nvar list = {instanceName: \"INSTANCE_NAME\", className: \"CLASS_NAME\"};\nvar fields = [\"release_year\", \"id\", \"pages\"];\nvar pageSize = 1;\n\nDataObject.please()\n .list(list)\n\t.fields(fields)\n\t.pageSize(pageSize)\n .then(callback);", "language": "javascript" } ] } [/block] The API will automatically create pages with size equal to `page_size` for you and provide a link to the next page. [block:code] { "codes": [ { "code": "{\n \"next\": \"/v1.1/instances/syncano/classes/books/objects/?direction=1&last_pk=2134&page_size=1&query=%7B%22release_year%22%3A%7B%22_gt%22%3A2%2C%22_lte%22%3A163%7D%2C%22pages%22%3A%7B%22_gt%22%3A12%7D%7D\", \n \"prev\": null, \n \"objects\": [\n {\n \"id\": 642, \n \"release_year\": 1985, \n \"pages\": 200\n }\n ]\n}", "language": "json" } ] } [/block] More info about paging can be found [here](http://docs.syncano.com/v0.1/docs/general-information#paging). [block:api-header] { "type": "basic", "title": "Summary" } [/block] In this chapter you have learned how to use filtering and ordering when making Data Object requests to Syncano. You have also learned how to combine the ordering and filtering queries and use paging on the top of that. Go to [Incrementing / decrementing fields](doc:incrementing-decrementing-fields) chapter to learn more about Data Objects and their properties.