1
votes

I am trying to write a table with various numbers of rows and columns to a database. For this, I have a Criterion collection that saves the table headers and an Option collection that saves the table data.

The structure is like this:

  • for Criterion:

    { { "_id" : "hId1", "name" : "Option Name", "tableId" : "tId1" }, { "_id" : "hId2", "name" : "Rent", "score" : 9, "tableId" : "tId1" }, { "_id" : "hId3", "name" : "Surface", "score" : 5, "tableId" : "tId1" }, { "_id" : "hId4", "name" : "Price", "score" : 5, "tableId" : "tId1" }, { "_id" : "hId5", "name" : "CPU", "score" : 5, "tableId" : "tId4" } etc. }

  • for Option:

    { { "_id" : "id1", "score" : 5, "hId1" : { "value" : "Apt 1" }, "hId2" : { "value" : "800 sqft", "score" : 1 }, "hId3" : { "value" : "$800", "score" : 3 }, etc. "tableId" : "tId1" } { "_id" : "id2", "score" : 5, "hId1" : { "value" : "Apt 2" }, "hId2" : { "value" : "780 sqft", "score" : 10 }, "hId3" : { "value" : "$700", "score" : 3 }, etc. "tableId" : "tId1" } etc. }

The first row for Criterion will always have "Option Name". For the data above, the table with "tableId" = "tId1" would end up looking like this (tableId and headerId are the keys):

| Option Name | Surface  | Price |
| =========== | ======== | ===== |
| Apt 1       | 800 sqft | $800  |
| Apt 2       | 780 sqft | $700  |

My code looks like this (imports/api/comparison.js):

/**
 * Options are for the rows
 */
export var Option = new Mongo.Collection('option');

/**
 * Criteria are the columns 
 */
export var Criterion = new Mongo.Collection('criterion');

Meteor.methods({
    'comparison.insertRow' (query, headerId, tableId, isFirst) {
        check(query, Object);
        check(headerId, String);
        check(tableId, String);
        check(isFirst, Boolean);

        if(isFirst){
            var data = {};
            data._id = headerId;
            data.tableId = tableId;
            data.name =  "Option Name";
            Criterion.insert(data);
        }

        query._id = tableId;
        Option.insert(query);
    },
});

Where isFirst is a boolean expressing whether this is the first row in a table or not.

My query is constructed like this (imports/ui/Menu/DataInsert.jsx):

    var query = {};
    query.score = // value
    // get the header separately
    query[headerId] = {
        value: //valueH from form
    };

    // Find the text field via the React ref
    for (var i = 1, len = cols.length; i < len; i++) {
        query[cols[i]._id] = {
            value: //valueV from form,
            score: //valueS from form
        };
    }

My files are available on the server because I am doing this in server/main.js: import '../imports/api/comparison.js';

The query gets inserted no problem into Option no problem.

Why isn't data getting inserted into Criterion (when isFirst = true)?

I did a console.log(data) and a console.log(query) and it looks like this: Devtools picture

whereas the data in the db looks like this: Terminal picture

1
It might be because you are manually setting the _id field before inserting. You should add a callback as the 2nd arg to Criterion.insert which accepts an error object as the first arg. Use that to check if the insert is throwing an error. Read the on server portion of the api - jordanwillis

1 Answers

0
votes

@jordanwillis was correct above, this was happening because I was setting the _id manually on the query. I did need to set the id, but I needed to set the tableId.

So, for the record, this is what I did:

'comparison.insertRow' (query, headerId, tableId, isFirst) {
    check(query, Object);
    check(headerId, String);
    check(tableId, String);
    check(isFirst, Boolean);

    if(isFirst){
        var data = {};
        data._id = headerId;
        data.tableId = tableId;
        data.name =  "Option Name";
        Criterion.insert(data);
    }

    query.tableId = tableId;
    Option.insert(query);
},

And my foreign keys are tableId and headerId (which is part of query).