Skip to content

Version 7.2.0

Compare
Choose a tag to compare
@notheotherben notheotherben released this 18 May 11:44
· 70 commits to main since this release

This release adds support for MongoDB's mapReduce operation thanks to a brilliant PR by @RagibHasin. It supports both inline mapReduce and reducing into a typed Iridium collection. It also includes a number of improvements to Iridum's documentation and some regression tests to help avoid situations like we saw in #73.

Using MapReduce

Inline Reduce

Inline reductions are great for once-off operations where you do not wish to persist the results to a collection. It allows you to provide a map and reduce function and will return the resulting documents that leave the reduce function.

interface MySourceDoc {
  _id: string;
  group_key: string;
  value: number;
}

@Iridium.Collection("source")
class MySourceModel extends Iridium.Instance<MySourceDoc, MySourceModel> {
  _id: string;
  group_key: string;
  value: number;
}

const core = new Iridium.Core("mongodb://localhost:27017")
await core.connect()

const source = new Iridium.Model<MySourceDoc, MySourceModel>(core, MySourceModel);

const result = await source.mapReduce({
  map: function() {
    emit(this.group_key, this.value);
  },
  reduce: function(key, values) {
    return Array.sum(values);
  }
}, { out: "inline" });

result.forEach(item => {
  console.log(`group '${item._id}': ${item.value}`);
});

Reduce into a Collection

In situations where you require more control over the documents you receive from mapReduce (performing transforms etc) you can use the @Iridium.MapReduce decorator function on an instance class and provide that to the mapReduce method call. This will allow you to retroactively access the results of the mapReduce operation in the specified @Iridium.Collection.

interface MySourceDoc {
  _id: string;
  group_key: string;
  value: number;
}

@Iridium.Collection("source")
class MySourceModel extends Iridium.Instance<MySourceDoc, MySourceModel> {
  _id: string;
  group_key: string;
  value: number;
}

interface MyReducedDoc {
  _id: string;
  value: number;
}

@Iridium.Collection("reduced")
@Iridium.MapReduce<MySourceDoc, string, number>(function() {
  emit(this.group_key, this.value);
}, function(key, values) {
  return Array.sum(values);
})
class MyReducedModel extends Iridium.Instance<MyReducedDoc, MyReducedModel> {
  _id: string;
  value: number;
}

const core = new Iridium.Core("mongodb://localhost:27017")
await core.connect()

const source = new Iridium.Model<MySourceDoc, MySourceModel>(core, MySourceModel);
const reduced = new Iridium.Model<MyReduceDoc, MyReduceModel>(core, MyReduceModel);

await source.mapReduce(reduced, { out: "replace" })
await reduced.find().forEach(item => {
  console.log(`group '${item._id}': ${item.value}`);
});