0

In my DynamoDB table I've got items with userA (MyUser) following UserB(myFriends..)

Primary-------|---- Srotkey---|---FriendID---|
 Myid.....       Friend-01        22223333

in the same table I also have the user profiles..

Primary-------|---- Srotkey---|----Name----|
 Myid.....       Friend-01
 22223333          Profile         Rose    

Now I want to have a a function to return my friend's profile. I suppose my lambda "getFriendProfile" function should do two queries, get the id for the person I'm following in the first query and then use that result to fetch her profile in the second query.

I know how to get those result individually but I don't know how to combine them and put them both into one function.

First query (getPeopleIFollow)

module.exports.handler = async (event, context, callback) => {

    const _userID = event.userID;

    var params = {
    TableName: "mytableName",
    ProjectionExpression: "FriendID",
    KeyConditionExpression: "#tp = :userId and begins_with(#sk, :skv)",
    ExpressionAttributeNames: {
      "#tp": "userId",
      "#sk": "Sortkey",
    },
    ExpressionAttributeValues: {
      ":userId": { "S": _userID },
      ":skv": { "S": "Friend" },

    }

    }
var Friend_ID;

try {

let data = await dynamodb.query(params).promise();

data.Items.map(
  (dataField) => {

  Friend_ID = dataField.FriendID.S,


  }

);

   callback(null, Friend_ID );

  }
  catch (error) {
    console.log(error);

    callback(error);
  }

};

My other function looks just looks very much like the first one.. getProfileNames..

module.exports.handler = async (event, context, callback) => {

    const _userID = event.myfriendID;

    var params = {
    TableName: "mytableName",
    ProjectionExpression: "Name",
    KeyConditionExpression: "#tp = :userId and begins_with(#sk, :skv)",
    ExpressionAttributeNames: {
      "#tp": "userId",
      "#sk": "Sortkey",
    },
    ExpressionAttributeValues: {
      ":userId": { "S": _userID },
      ":skv": { "S": "Profile" },

    }

    }
try {

let data = await dynamodb.query(params).promise();

const items = data.Items.map(
  (dataField) => {

      return {
        friend_name: dataField.Name.S,

    }

  }


);

   callback(null, items );

  }
  catch (error) {
    console.log(error);

    callback(error);
  }

};

1 Answer 1

1

Keeping functionality separate to each Lambda is actually a nice way to organise code. So you could keep your code as it is and invoke the getProfileNames lambda for each of the getPeopleIFollow results.

I think it's also a good idea to abstract as much as possible out of your handler so that it becomes easy to follow at a high level. So the following examples assumes your code is in other functions that return promises.

(untested code)

module.exports.handler = async (event, context, callback) => {
    const _userID = event.userID;
    try {
        const userFriends = await getUserFriends(userId);
        const friendProfiles = await getFriendProfiles(userFriends);
        callback(null, friendProfiles );
    } catch (error) {
        console.log(error);
        callback(error);
    }
}

The lambda invocation happens in getFriendProfiles which uses Promise.all to invoke lambdas for each separate friendProfile request.

(untested code)

function getFriendProfiles(userFriends){
    return Promise.all(userFriends.map(userFriend => {
        const params = {
            ClientContext: "MyApp", 
            FunctionName: "MyFunction", 
            InvocationType: "RequestResponse", // important, you choose this so you get a response otherwise (eg if you choose the 'Event' InvocationType) I think the promise will resolve once the invocation is successful
            LogType: "Tail", 
            Payload: JSON.stringify({ myfriendID: userFriend }), // I think this is right, I usually use pathParameters or body for my payloads
            Qualifier: "1"
        };
        lambda.invoke(params).promise();
    });
}

Having said all that - what this number of db queries shows is that perhaps this DynamoDb schema is not the most efficient. This might be a case where indexes could be helpful, or even using an RDS rather than dynamodb.

Sign up to request clarification or add additional context in comments.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.