{"id":13426080,"url":"https://github.com/koopjs/winnow","last_synced_at":"2025-04-09T16:15:45.797Z","repository":{"id":4133740,"uuid":"52110344","full_name":"koopjs/winnow","owner":"koopjs","description":"Deprecated","archived":false,"fork":false,"pushed_at":"2023-08-13T20:04:33.000Z","size":29463,"stargazers_count":89,"open_issues_count":15,"forks_count":18,"subscribers_count":15,"default_branch":"master","last_synced_at":"2025-04-09T16:15:37.997Z","etag":null,"topics":["deprecated","geojson","in-memory-database","sql","typesript"],"latest_commit_sha":null,"homepage":"","language":"JavaScript","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"apache-2.0","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/koopjs.png","metadata":{"files":{"readme":"README.md","changelog":"CHANGELOG.md","contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null}},"created_at":"2016-02-19T19:14:26.000Z","updated_at":"2024-11-20T03:20:58.000Z","dependencies_parsed_at":"2023-07-06T07:28:37.153Z","dependency_job_id":"ee84555f-b649-4442-b901-27e62b5c7c26","html_url":"https://github.com/koopjs/winnow","commit_stats":{"total_commits":343,"total_committers":19,"mean_commits":18.05263157894737,"dds":0.6618075801749271,"last_synced_commit":"8b9b650ddf870de30fbff5afcc76d306930d4cdd"},"previous_names":["dmfenton/winnow"],"tags_count":82,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/koopjs%2Fwinnow","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/koopjs%2Fwinnow/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/koopjs%2Fwinnow/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/koopjs%2Fwinnow/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/koopjs","download_url":"https://codeload.github.com/koopjs/winnow/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":248065282,"owners_count":21041872,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["deprecated","geojson","in-memory-database","sql","typesript"],"created_at":"2024-07-31T00:01:25.886Z","updated_at":"2025-04-09T16:15:45.759Z","avatar_url":"https://github.com/koopjs.png","language":"JavaScript","readme":"# Winnow\n\n## DEPRECATED - now migrated to a package in the [Koop monorepo](https://github.com/koopjs/koop/).  Update any `npm` usage to `@koopjs/winnow`.\n\n[![No Maintenance Intended](http://unmaintained.tech/badge.svg)](http://unmaintained.tech/)\n[![npm version][npm-img]][npm-url]\n[![js-standard-style][standard-img]][standard-url]\n[![Greenkeeper badge][greenkeeper-image]][greenkeeper-url]\n\n*Winnow* is made for applying sql to geojson in memory. It is useful for working against geojson objects but also has built-in primitives for piping streams.\n\n# API\n## `winnow.query`\nBuild and apply a query to a feature collection object or an array of features\n\n```javascript\nconst features = Object\nconst options = {\n  where: String // A sql where statement\n  geometry: Object // GeoJSON or Esri geometry Object\n  spatialPredicate: String // ST_Within || ST_Contains || ST_Intersects\n  fields: Array // Set of fields to select from feature properties\n  aggregates: Object // Describes the set of aggregations to perform on fields\n  groupBy: Array // Set of fields for grouping statistics\n  limit: Number // number of results to return\n  offset: Number // number of return features to offset\n  order: Array // Set of fields or aggregates by which to order results\n  outputCrs: Number || String // An EPSG code, an OGC WKT or an ESRI WKT used to convert geometry\n  inputCrs: Number || String // An EPSG code, an OGC WKT or an ESRI WKT defining the coordinate system of the input data. Defaults to 4326 (WGS84)\n  toEsri: Boolean // return Esri feature collection\n  geometryPrecision: Number // number of digits to appear after decimal point for geometry\n  classification: Object // GeoJSON or geoservices classification Object\n}\nwinnow.query(features, options)\n// Returns the set of features that match the query\n```\n\n### `where`\nA sql where statement.\n\n- `'Trunk_Diameter \u003e 10'`\n- `'Trunk_Diameter \u003e 10 AND Genus like 'Quercus%'`\n- `(Genus like '%Quercus%' OR Common_Name like '%Live Oak%') AND Street_Type like '%AVE%'`\n\n\n### `geometry`\nA GeoJSON or Esri Geometry Object\n```javascript\n// GeoJSON Polygon\n{\n  type: 'Polygon',\n  coordinates: [[[-118.163, 34.162], [-118.108, 34.162], [-118.108, 34.173], [-118.163, 34.173], [-118.163, 34.162]]],\n}\n\n// Esri Envelope (aka Bounding box)\n{\n xmin: -13155799.066536672,\n ymin: 4047806.77771083,\n xmax: -13143569.142011061,\n ymax: 4050673.16627152,\n spatialReference: {\n   wkid: 102100\n }\n}\n```\n### `spatialPredicate`\nSpecifies the relationship between the passed-in geometry and the features in the data\n\n- ST_Within: Features in the data must be completely within the passed-in geometry\n- ST_Contains: Features in the data must completely contain the passed-in geometry\n- ST_Intersects: Features in the data must intersect the passed-in geometry\n\nCan also specify the esri-style predicates `esriSpatialRelWithin, esriSpatialRelContains, esriSpatialRelIntersects`\n\n### `fields`\nAn array that specifies fields should be returned from each features properties or attributes. Will also accept a comma-delimited string.\n\ne.g. `[Trunk_Diameter, Common_Name, Genus]`\n\n### `aggregates`\nAn array that specifies aggregations to apply across all features or properties. Must specify at least a type and a field. Providing a name for the aggregation is optional\n\nTypes: `[sum, avg, count, max, min, first, last]`\n\ne.g:\n```javascript\n[\n  {\n    type: 'sum',\n    field: 'Trunk_Diameter',\n    name: 'Total_Trunk_Diameter'\n  },\n  {\n    type: 'avg',\n    field: 'Trunk_Diameter'\n  }\n]\n```\n\n### `groupBy`\nAn array of fields used to group the results. Must be used with aggregates. Note this will not return any geometry\n\n### `limit`\nThe total number of results to return\n\n### `offset`\nThe amount to offset returned features (e.g., `10` will skip the first 10 returned features). `limit` is required to used `offset`.\n\n### `order`\nAn array of fields use to sort the output\n\n### `outputCrs` (formerly `projection`)\nCan be an EPSG code, an OGC wkt or an Esri wkt. This parameter controls how the geometry will be projected to another coordinate system.\n\n### `inputCrs`\nCan be an EPSG code, an OGC wkt or an Esri wkt.. This parameter defines the coordinate system of input data. If the incoming data is a GeoJSON feature collection with a \"named\" `crs` property defined according to [specification](https://geojson.org/geojson-spec#named-crs), winnow will use it's value if `inputCrs` is undefined. If neither is defined, Winnow assumes the input data has coordinate system WGS84.\n\n### `toEsri`\nIf true, the object returned will be an esri feature collection.\n\nWinnow will automatically determine field types from the first feature passed in. If a given attribute is null, Winnow will assume it is a string.\n\nYou can also pass in a metadata object that describes the fields in the feature collection. This is recommended if you know your schema ahead of time\n\ne.g.\n\n```javascript\n{\n  type: 'FeatureCollection',\n  features: [],\n  metadata: {\n    fields: [\n      {\n        name: 'SomeDateField',\n        type: 'Date'\n      },\n      {\n        name: 'SomeDoubleField',\n        type: 'Double'\n      },\n      {\n        name: 'SomeIntegerField',\n        type: 'Integer'\n      },\n      {\n        name: 'SomeStringField',\n        type: 'String'\n      }\n    ]\n  }\n}\n```\n\n### `geometryPrecision`\nA number for geometry precision. Geometry values will be truncated to the supplied decimal place.\n\n### `classification`\nAn object for classification aggregation. Classification ouputs an array of breaks on features. There are two supported classification types: _Class Breaks_ and _Unique Value_. Classification supports input from FeatureServer's [generateRenderer](https://github.com/FeatureServer/FeatureServer#generateRenderer) _classificationDef_.\n\n##### `Class Breaks`\n_Class Breaks_ is used to classify numeric data based on a number of breaks and a statistical method. Features can also be normalized before being classified.\n\n```javascript\n{\n  *type: 'classes',\n  *field: '\u003cfield1\u003e',\n  *method: 'equalInterval' | 'naturalBreaks' | 'quantile' | 'std',\n  *breakCount: 7,\n   normType: 'field' | 'log' | 'percent',\n   normField: '\u003cfield2\u003e' // mandatory if normType === 'field'\n}\n*required\n```\ne.g. An example feature collection has a field called _field1_ ranging in value from 0 - 29.\n\nInput:\n\n```javascript\n{\n  type: 'classes',\n  field: 'field1',\n  method: 'equalInterval',\n  breakCount: 5,\n}\n```\n\nOutput (array of class intervals):\n\n```javascript\n[ [0-5],\n  [6-11],\n  [12-17],\n  [18-23],\n  [24-29] ]\n```\n\n##### `Unique Value`\n_Unique Value_ is used to classify data based on a unique field(s). The output is an array of objects for each unique value combination. Each object contains an instance count, and the classifying unqiue field names and values.\n\n```javascript\n{\n  *type: 'unique',\n  *fields: ['\u003cfield1\u003e', '\u003cfield2\u003e', '\u003cfield3\u003e'] // up to three fields\n}\n*required\n```\n\ne.g. An example feature collection has unique fields called _employeeID_ and _customerID_.\n\nInput:\n\n```javascript\n{\n  type: 'unique',\n  fields: ['employeeID', 'customerID']\n}\n```\n\nOutput (array of instance objects):\n\n```javascript\n[\n  {count: 3, employeeID: 'A', customerID: 'M'},\n  {count: 1, employeeID: 'A', customerID: 'N'},\n  {count: 1, employeeID: 'B', customerID: 'M'},\n  {count: 2, employeeID: 'B', customerID: 'N'},\n  {count: 2, employeeID: 'B', customerID: 'O'},\n  {count: 1, employeeID: 'C', customerID: 'O'},\n]\n```\n\n## `winnow.prepareQuery`\nReturns a function that can be applied directly to a feature collection object, an array of features, or a single feature. Useful when you want to pass a stream of features through a filter.\n\n```javascript\nconst options = {\n  where: String,\n  geometry: Object,\n  spatialPredicate: String,\n  fields: Array,\n  aggregates: Array\n}\nconst filter = winnow.prepareQuery(options)\nfilter(geojson)\n// returns the set of feature that match the query\n```\n\n## `winnow.querySql`\nExecute sql directly against the query engine.\n\n- Replace any variables with ?\n - Table name should always be replaced by ?\n - Non-string values always be replaced by ?\n\n\n ```javascript\n const statement = 'Select * from ? where Genus in ?'\n const data = geojson\n const genus = ['Quercus']\n winnow.querySql(statement, [geojson, genus])\n // returns all features that match the query\n ```\n\n## `winnow.prepareSql`\nPass in a statement and return a filter than can be applied to a feature collection object, an array of features or a single feature. Variables work in the same way as `winnow.sql`\n\n```javascript\nconst statement = 'Select Trunk_Diameter from ? where Trunk_Diameter \u003e 100'\nconst filter = winnow.prepareSql(statement)\nfilter(geojson)\n// returns all the features that match the query\n```\n\n## OBJECTID generation\nWhen option `toEsri` is `true`, winnow will check that features have a unique-identifier field. This is field is flagged with the `idField` option.  If not present, winnow will look for a field named `OBJECTID` and use it as the unique-identifier by default.  If no `OBJECTID` is present, winnow creates one by generating a numeric hash of the feature. By default, winnow uses FarmHash for hashing. Some cloud deployments currently have trouble executing Farmhash (Heroku, 2020-09-30), so you can use native Javascript hashing as an alternative. Simply set the environment variable `OBJECTID_FEATURE_HASH=javascript`.\n\n# Issues\n\nFind a bug or want to request a new feature? Please let us know by submitting an [issue](https://github.com/FeatureServer/winnow/issues).\n\n# Contributing\n\nEsri welcomes contributions from anyone and everyone. Please see our [guidelines for contributing](https://github.com/Esri/contributing) and the [RELEASE.md](RELEASE.md) for a description of our release process.\n\n# License\n\n[Apache 2.0](LICENSE)\n\n[npm-img]: https://img.shields.io/npm/v/winnow.svg?style=flat-square\n[npm-url]: https://www.npmjs.com/package/winnow\n[travis-img]: https://img.shields.io/travis/koopjs/winnow/master.svg?style=flat-square\n[travis-url]: https://travis-ci.org/koopjs/winnow\n[standard-img]: https://img.shields.io/badge/code%20style-standard-brightgreen.svg\n[standard-url]: http://standardjs.com/\n[greenkeeper-image]: https://badges.greenkeeper.io/koopjs/winnow.svg\n[greenkeeper-url]: https://greenkeeper.io/\n","funding_links":[],"categories":["JavaScript"],"sub_categories":[],"project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fkoopjs%2Fwinnow","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fkoopjs%2Fwinnow","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fkoopjs%2Fwinnow/lists"}