Coalesce Strategy
coalesce-strategy is a nodejs module that allows you to create relatively* complex merging strategies for javascript objects. This module really shines if you're consuming json objects from various services and you need fine grained control over which fields you'll use in your application.
*coalesce-strategy doesn't support deep priorities i.e flat objects are preferred.
Install
$ npm install --save coalesce-strategy
Purpose
For example, if you created an app that gathered ID3 tag data for songs from various services, you would probably want to cherry pick which field gets used from each service. e.g always use song titles from Spotify, but only use genres from Lastfm.
And before now you would probably hard code this manually. And this may be ok for 2 services, but when you need to coalesce objects from 10+ services the code gets unwieldy and unmanageable. Especially in a real life scenario where the items you're merging may be missing fields. e.g if Lastfm was missing genre data, you would probably want to fallback to Spotify.
And that's where coalesce-strategy comes into play. It allows you to define a strategy object which has the strategies and priorities that should be used to coalesce your items.
Quick Example
Based on our song meta data example above, here's how we would solve our problem using coalesce-strategy
First lets define our strategy file(basic_strat.json):
"strategies": "Spotify" : "priorities": "title": 10 "Lastfm" : "priorities": "genre": 3 "releaseDate": 3
Now for the coalescing:
// load our strategyvar strategy = ; // define our central model to coalesce againstvar songModel = title: '' genre: '' releaseDate: '' length: ''; var merger = strategy songModel; var items = ;items;items; // anonymous items have priorities of 0items; // coalesce our itemsmerger;
By using coalesce-strategy we no longer have to hard code the properties we wish to use and allows us to quickly and easily modify existing priorities, as well as add new strategies when we add additional services. All without changing existing code logic.
Documentation
Methods
Modifiers
- Understanding Modifiers & Priorities (Intro)
winOnDefault
ignore
useOnly
baseline
priority
skipKeysWithFunctionValues
allowMergingOfEmptyValues
Methods ### createItem ([id] , item)
Wraps item
into an object with the specified a id
which can be understood by the library.
The id
should match an existing id in the strategy object. Items without an id
will be assigned a randomly generated id
and all properties will be treated as having an priority of 0.
Arguments
id
- The id of the strategy.item
- The data/payload.
Returns
{object}
- a strategy item.
Examples
// strategy.json "strategies": "Spotify" : "priorities": "title": 10
// Anonymous itemvar item1 = merger; // Item with an idvar item2 = merger;
### merge (items, callback)
Merges/Coalesces an array
of strategy items into a central model.
Arguments
items
- An array of strategy items.callback(err, result)
- A callback which is called when the coalescing is complete.result
will be the initial model with its property values modified to conform to the desired priorities.
As of writing the err
parameter is unused and will always be assigned null
. This is to remain compatible with libraries that require the traditional callback(err, data)
pattern.
Examples
// basic_strat.json "strategies": "Spotify" : "priorities": "title": 10 "Lastfm" : "priorities": "genre": 3 "releaseDate": 3
// load our strategyvar strategy = ; // define our central model to coalesce againstvar songModel = title: '' genre: '' releaseDate: '' length: ''; // initialize coalesce strategy libraryvar merger = strategy songModel; var items = ;items;items; // anonymous items have priorities of 0items; // coalesce our itemsmerger;
Modifiers ### Understanding Modifiers & Priorities (Intro)
Modifiers are a powerful feature of coalesce-strategy that allows intricate customization of the coalescing process. Coalesce-strategy supports blacklisting and whitelisting of properties, as well as a few other customization options.
To understand the modifier documentation below, it's important to understand the various levels/ways a modifier can be set inside a strategy file(model
, strategy
, priority
).
Modifiers set on the strategy
level affects all properties on that item(including ones that aren't explicitly defined).
A strategy object inside a strategy file does not need to include every property an item may have. Anything not given an explicit priority will be assumed to have a priority of 0.
// SomeStrategyFile.json "model" : "ignore": "title" // set on the "Model" level "strategies": "Spotify": // Spotify Strategy "winOnDefault": false // set on the "Strategy" level "priorities": "title": 10 "release-date": // setting a priority using an object "winOnDefault": true // set on the "Priority" level "priority": 5 "genre": 2
### winOnDefault
Generally the property with the highest priority always wins, but when two or more properties have the same priority, we refer to this as the "Default" or "Conflict" state. This modifier allows coalesce-strategy to decide who should "win" in that scenario.
Without the use of winOnDefault
the item who appears later in the array of strategy items wins.
Supported On
strategy
priority
Type
boolean
Examples
//basic_strat.json "strategies": "Spotify" : "priorities": "title": 10 "Lastfm" : "priorities": "title": "winOnDefault": true "priority": 10 "releaseDate": 3 "rdio" : "winOnDefault": false "priorities": "releaseDate": 3
var strategy = ;var songModel = title: '' genre: '' releaseDate: '' length: ''; var merger = strategy songModel; var items = ;items;items;items; merger;
### ignore
A blacklist of properties. Properties that are blacklisted will be ignored during the coalescing process.
Supported On
model
strategy
Type
array
Examples
//basic_strat.json "model": "ignore": "author" "strategies": "BarnesNobles": {} "Amazon": "ignore": "summary"
var strategy = ;var bookModel = title: '' author: '' summary: '' rating: '';var merger = strategy bookModel;var items = ;items;items;merger;
### useOnly
A whitelist of properties. Only properties listed in the array will be used to populate the central model.
Supported On
model
strategy
Type
array
Examples
//basic_strat.json "model": "useOnly": "studio" "rating" "revenue" "strategies": "IMDB": "useOnly": "rating" "metacritic": "useOnly": "title" "revenue"
var strategy = ;var movieModel = title: '' studio: '' rating: '' revenue: '';var merger = strategy movieModel;var items = ;items;items;items;merger;
### baseline
Shifts the priorities of all the properties on an strategy. This also applies to properties that are not explicitly defined in the strategy file. The property's final priority will be the sum of the baseline and the property's own priority(if defined).
Supported On
strategy
Type
number
Examples
//basic_strat.json "strategies": "npm": "baseline": 10 "priorities": "maintainer": 5 "enterprise": "priorities": "maintainer": 8 "packageName": 6
var strategy = ;var npmModel = packageName: '' maintainer: '';var merger = strategy npmModel;var items = ;items;items;merger;
### priority
Sets the priority of a particular property. Useful when combining multiple modifiers at the priority
level.
Supported On
priority
Type
number
Examples
//basic_strat.json "strategies": "npm": "priorities": "maintainer": 5 "downloads": "priority": 10 "winOnDefault": true
### skipKeysWithFunctionValues
Any property/key on the central model object that has been assigned a function
will be ignored during the coalescing process.
Supported On
model
Type
boolean
Examples
//basic_strat.json "model": "skipKeysWithFunctionValues": true "strategies": "npm": "priorities": "maintainer": 5
var strategy = ;var npmModel = packageName: '' { console; };var merger = strategy npmModel;var items = ;items;merger;
### allowMergingOfEmptyValues
Optionally disable coalescing properties with empty
values.
Default is true
.
Supported On
model
Type
boolean
Examples
//basic_strat.json "model": "allowMergingOfEmptyValues": false
var strategy = ;var npmModel = packageName: 'coalesce-strategy';var merger = strategy npmModel;var items = ;items;merger;
And just so there's no confusion as to what qualifies as empty
:
var merger = ;console; // => trueconsole; // => trueconsole; // => trueconsole; // => trueconsole; // => trueconsole; // => trueconsole; // => falseconsole; // => falseconsole; // => falseconsole; // => falseconsole; // => falseconsole; // => false
Never EVER use anything under tests
. It's only exposed for unit testing purposes. You have been warned.
License
The MIT License (MIT)
Copyright (c) 2015 Paul J. Miller
Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.