Skip to content

Need clarification on Transform behavior. #618

@hypercub3d

Description

@hypercub3d

Hi,

I'm having some trouble understanding how to correctly use the collection transforms. More specifically, I'm trying to figure out the correct way that the eqJoin and map transforms should be used.

Given this setup code:

const loki = require( 'lokijs' );
const lokiMem = new loki.LokiMemoryAdapter();
const db = new loki( 'my.db', { adapter: lokiMem } )
const coll = db.addCollection( 'mycoll', { unique: ['test'] } );

const data = [
      { test: 'a' },
      { test: 'b' },
      { test: 'c' },
      { test: 'e' },
      { test: 'd' },
      { test: 'g' },
      { test: 'f' },
    ];

const jdata = [
      { id: 'b', a: 1, b: 2 },
      { id: 'c', a: 1, b: 2 },
      { id: 'd', a: 1, b: 2 },
      { id: 'e', a: 1, b: 2 },
      { id: 'f', a: 1, b: 2 },
      { id: 'h', a: 1, b: 2 },
    ];

coll.insert(data);

I'd like to to join the data and jdata docsets. So I create a transform to allow me to do this.

coll.addTransform( 'testTrx', [
        {
          type: 'eqJoin',
          joinData: jdata,
          leftJoinKey: 'test',
          rightJoinKey: 'id'
        } 
] );

let out = coll.chain( 'testTrx' ).data();
console.log(out)

So, without providing a mapFun option to the eqJoin transform, the standard mapping function is applied yielding output that looks like this.

[
        {
            "left": {
                "test": "a",
                "meta": {
                    "revision": 0,
                    "created": 1506731589008,
                    "version": 0
                },
                "$loki": 1
            },
            "right": {}
        },
        {
            "left": {
                "test": "b",
                "meta": {
                    "revision": 0,
                    "created": 1506731589008,
                    "version": 0
                },
                "$loki": 2
            },
            "right": {
                "id": "b",
                "a": 1,
                "b": 2
            }
        },

... 
]

But I would rather have the data be joined directly into the document, so I modify the transform to look like this.

coll.addTransform( 'testTrx', [
        {
          type: 'eqJoin',
          joinData: jdata,
          leftJoinKey: 'test',
          rightJoinKey: 'id',
          mapFun: function( left, right ) {
            left = Object.assign( left, right );
            return left;
          }
        } 
] );

But when I invoke the transform, I get this error: Error: Document is already in collection, please use update()

It seems as if the data is being re-inserted into the collection, and the unique keys are clashing. So I attempted to strip the metadata from the record.

coll.addTransform( 'testTrx', [
        {
          type: 'eqJoin',
          joinData: jdata,
          leftJoinKey: 'test',
          rightJoinKey: 'id',
          mapFun: function( left, right ) {
            left = Object.assign( left, right );
            delete left.meta;
            delete left.$loki;
            return left;
          }

        } 
] );

Doing this yields the correct output:

[
        {
            "test": "a",
            "meta": {
                "revision": 0,
                "created": 1506732466194,
                "version": 0
            },
            "$loki": 1
        },
        {
            "test": "b",
            "id": "b",
            "a": 1,
            "b": 2,
            "meta": {
                "revision": 0,
                "created": 1506732466194,
                "version": 0
            },
            "$loki": 2
        },
...
]

This same behavior also occurs if I use the map transform and attempt to project the dataset. I need to strip the loki metadata, otherwise I get the same error as before.

If transforms are meant to be a way to restructure the dataset for output, does it make sense to have to manually strip the document metadata anytime the data needs to be changed?

The error advises me to use update, but as far as I understand, that modifies the original data.

Is there a better way to restructure or "project" data for use in views or as a means for output only?

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions