11

I am working with AWS DynamoDB and Dynamoose trying to fetch records using Scan function, but facing an issue that is not recognizable for me.

Stragenly, it's able to fetch records from another table in the same way and successfully get the records.

Here's my Code:

const vehicleMasterSchema = new dynamoose.Schema({
    "id": String,
    "customer_account_number": String,
    "fuel_type": String,
    "make": String,
    "model": String,
    "odometer_gatex": String,
    "plate_no": String,
    "rfid_gatex": String,
    "sales_agreement_id": String,
    "vehicle_category": String,
    "vehicle_id": String,
}, {
    "timestamps": {
        "createdAt": "create_date",
        "updatedAt": null // updatedAt will not be stored as part of the timestamp
    }
});
const vehicleMasterModel = dynamoose.model("vehicle_master", vehicleMasterSchema, { "create": false });

router.post('/getFuelingStatus', (req, res) => {
    var companyInfo = req.body;
    try {
        console.log(typeof vehicleMasterModel);
        vehicleMasterModel.scan("customer_account_number").eq(companyInfo.customerId).exec((error, results) => {
            if (error) {
                console.error(error);
            } else {
                res.json(results);
            }
        });
    } catch (error) {
        res.json(error);
    }
});

The TypeMismatch error is coming up only for this model same code is working for the other table.

Console Error

console error

My Table

table data

This appears to be related to this github issue on Dyanmoose

KyleMit
  • 30,350
  • 66
  • 462
  • 664
Owais Aslam
  • 1,577
  • 1
  • 17
  • 39
  • My guess is that you have a property value that is `null` in your table. – Charlie Fish Jul 06 '20 at 17:29
  • @CharlieFish nothing is null in my table. – Owais Aslam Jul 06 '20 at 17:53
  • Hmm. Not sure what this could be then. I'd probably need more information about the items/documents in your table. I don't think I'd be able to reproduce this with the info you gave. There is some item that it's trying to parse where `model` expects it to be a string but is instead an object. – Charlie Fish Jul 06 '20 at 18:38
  • Do you happen to have any property values that are null? – Charlie Fish Jul 07 '20 at 16:32
  • no, every column always has its value. @CharlieFish – Owais Aslam Jul 08 '20 at 13:33
  • 2
    When I worked with Dynamo I frequently saw the pattern where strings in the response were like this: "firstName": {"S": "John"}. Is it possible this could be the format of your data? Strange that it works the same on other tables tho. – Adam Specker Nov 12 '20 at 19:23
  • @AdamSpecker, that's exactly the issue that I see as well - but can it be fixed? – KyleMit Nov 12 '20 at 19:38
  • Sure, change the types in the schema from String to object, or Object : {S: string}. Haven't used TS in a bit so don't know if those are the exact right types but you get the idea. – Adam Specker Nov 12 '20 at 20:38

3 Answers3

4

My guess is that the problem could be related with the name of your attribute, model.

In fact, this is the actual case: the following code, extracted from the source code in Document.ts is the one which is overwriting your model property:

Object.defineProperty(this, "model", {
  "configurable": false,
  "value": model
});

This is how the Document looks like before:

document before

And after the execution of the aforementioned code:

document after

This code is executed when processing the Scan exec function in DocumentRetriever.ts when the library maps every Item returned by DynamoDB to their internal Document representation, exactly in this line of code:

const array: any = (await Promise.all(result.Items.map(async (item) => await new this.internalSettings.model.Document(item, {"type": "fromDynamo"}).conformToSchema({"customTypesDynamo": true, "checkExpiredItem": true, "saveUnknown": true, "modifiers": ["get"], "type": "fromDynamo"})))).filter((a) => Boolean(a));

The error you reported is a consequence of that change when the type of the returned Item is checked against your schema model in the checkTypeFunction:

const {isValidType, matchedTypeDetails, typeDetailsArray} = utils.dynamoose.getValueTypeCheckResult(schema, value, genericKey, settings, {"standardKey": true, typeIndexOptionMap});
if (!isValidType) {
  throw new Error.TypeMismatch(`Expected ${key} to be of type ${typeDetailsArray.map((detail) => detail.dynamicName ? detail.dynamicName() : detail.name.toLowerCase()).join(", ")}, instead found type ${typeof value}.`);
...

Please, try a different name, I think it will work properly.

jccampanero
  • 50,989
  • 3
  • 20
  • 49
  • Hey jcc, the `model` name is certainly confusing, but I don't think it's the underlying issue. I have the same problem with `imageUrl` as my property name. I added a link in the question to a [github issue](https://github.com/dynamoose/dynamoose/issues/1023#issuecomment-726350584) with a larger discussion and more resources. – KyleMit Nov 12 '20 at 22:22
  • Hi Kyle. Thank you very much for sharing the link, I will review it. And thank you very much for the clarification: certainly, if you are getting the same error with other property name, the issue probably should be other. I am reviewing the library source code trying to dig into it. Please, can you tell me which version of the library are you using? – jccampanero Nov 12 '20 at 22:38
  • Hey Jcc, thanks! Using the latest version on `2.3.0`. If you get in a PR to the repo or an [MCVE], definitely 500+ rep coming your way :) – KyleMit Nov 12 '20 at 22:40
  • @KyleMit, how does the actual data you exemplified in the GitHub issue looks like? Please, can you provide some samples of the items actually returned by DynamoDB? On the other hand, the error appears always, randomly? Please, can you provide any feedback? – jccampanero Nov 13 '20 at 11:53
  • 1
    @KyleMit I see you've done some investigation on this, but after reading everything, I find myself to believe that your case has some other problem than this Q here and the [github issue](https://github.com/dynamoose/dynamoose/issues/1023#issuecomment-726350584). I believe you should have created a new question with your case (schemas/code) to help people trying to figure this out. – Christos Lytras Nov 13 '20 at 14:05
  • 1
    @ChristosLytras - fair point and I might open an issue if I can tease out an MCVE, but my case is intertwined with a big code base so I have to do a lot of work before posting an issue. In the meantime, this is the highest voted dynamoose question of all time w/ 0 answers as of yesterday. Bountying it up for visibility. Folks can feel free to answer without regard to my particular use case, but I suspect something similar is going on for the people who have voted it up. – KyleMit Nov 13 '20 at 14:17
  • 1
    @KyleMit I updated my answer with further information. I am afraid that perhaps your problem is not related with the Owais. As you can see, I think his problem is clearly identified. Please, if you consider it appropriate, expand the question with further information about your problem, I will try to help if I can. – jccampanero Nov 15 '20 at 14:01
1

Schema must be like this :

const ImageGalleryFoldersSchema = new Schema({
  key: {
    type: String,
    hashKey: true,
    required: true,
  },
  displayName: {
    type: String,
    required: true,
  },
  parentFolderKey: {
    type: String,
    required: false,
  },
  isActive: {
    type: Boolean,
    default: true,
    required: false,
  },
}, {
  timestamps: true,
});
user4157124
  • 2,809
  • 13
  • 27
  • 42
Pavel
  • 155
  • 1
  • 2
0

Maybe your problem is caused due to asynchronous behaviour.

To be more specific, I think that by the time you call the "scan"-function-chain the body-request has not been finished. However, due to the nature of Hoisting, the object "companyInfo" was already being initialised before you enter the function-call.

Therefore, you may get the specified "TypeMismatch"-error.

Could you please try implementing the following async/await-structure and tell me if this helps:

router.post('/getFuelingStatus', async (req, res) => {
    var companyInfo = await req.body;
    try {
        console.log(typeof vehicleMasterModel);
        vehicleMasterModel.scan("customer_account_number").eq(companyInfo.customerId).exec((error, results) => {
            if (error) {
                console.error(error);
            } else {
                res.json(results);
            }
        });
    } catch (error) {
        res.json(error);
    }
});