Returning a document with two fields from the same array in MongoDB











up vote
4
down vote

favorite












Given documents such as



{
_id: 'abcd',
userId: '12345',
activities: [
{ status: 'login', timestamp: '10000001' },
{ status: 'logout', timestamp: '10000002' },
{ status: 'login', timestamp: '10000003' },
{ status: 'logout', timestamp: '10000004' },
]
}


I am trying to create a pipeline such as all users that have their latest login/logout activities recorded between two timestamps will be returned. For example, if the two timestamp values are between 10000002 and 10000003, the expected document should be



{
_id: 'abcd',
userId: '12345',
login: '10000003',
logout: '10000002'
}


Of if the two timestamp values are between -1 and 10000001, the expected document should be :



{
_id: 'abcd',
userId: '12345',
login: '10000001',
logout: null
}


Etc.



I know it has to do with aggregations, and I need to $unwind, etc., but I'm not sure about the rest, namely evaluating two fields from the same document array










share|improve this question




























    up vote
    4
    down vote

    favorite












    Given documents such as



    {
    _id: 'abcd',
    userId: '12345',
    activities: [
    { status: 'login', timestamp: '10000001' },
    { status: 'logout', timestamp: '10000002' },
    { status: 'login', timestamp: '10000003' },
    { status: 'logout', timestamp: '10000004' },
    ]
    }


    I am trying to create a pipeline such as all users that have their latest login/logout activities recorded between two timestamps will be returned. For example, if the two timestamp values are between 10000002 and 10000003, the expected document should be



    {
    _id: 'abcd',
    userId: '12345',
    login: '10000003',
    logout: '10000002'
    }


    Of if the two timestamp values are between -1 and 10000001, the expected document should be :



    {
    _id: 'abcd',
    userId: '12345',
    login: '10000001',
    logout: null
    }


    Etc.



    I know it has to do with aggregations, and I need to $unwind, etc., but I'm not sure about the rest, namely evaluating two fields from the same document array










    share|improve this question


























      up vote
      4
      down vote

      favorite









      up vote
      4
      down vote

      favorite











      Given documents such as



      {
      _id: 'abcd',
      userId: '12345',
      activities: [
      { status: 'login', timestamp: '10000001' },
      { status: 'logout', timestamp: '10000002' },
      { status: 'login', timestamp: '10000003' },
      { status: 'logout', timestamp: '10000004' },
      ]
      }


      I am trying to create a pipeline such as all users that have their latest login/logout activities recorded between two timestamps will be returned. For example, if the two timestamp values are between 10000002 and 10000003, the expected document should be



      {
      _id: 'abcd',
      userId: '12345',
      login: '10000003',
      logout: '10000002'
      }


      Of if the two timestamp values are between -1 and 10000001, the expected document should be :



      {
      _id: 'abcd',
      userId: '12345',
      login: '10000001',
      logout: null
      }


      Etc.



      I know it has to do with aggregations, and I need to $unwind, etc., but I'm not sure about the rest, namely evaluating two fields from the same document array










      share|improve this question















      Given documents such as



      {
      _id: 'abcd',
      userId: '12345',
      activities: [
      { status: 'login', timestamp: '10000001' },
      { status: 'logout', timestamp: '10000002' },
      { status: 'login', timestamp: '10000003' },
      { status: 'logout', timestamp: '10000004' },
      ]
      }


      I am trying to create a pipeline such as all users that have their latest login/logout activities recorded between two timestamps will be returned. For example, if the two timestamp values are between 10000002 and 10000003, the expected document should be



      {
      _id: 'abcd',
      userId: '12345',
      login: '10000003',
      logout: '10000002'
      }


      Of if the two timestamp values are between -1 and 10000001, the expected document should be :



      {
      _id: 'abcd',
      userId: '12345',
      login: '10000001',
      logout: null
      }


      Etc.



      I know it has to do with aggregations, and I need to $unwind, etc., but I'm not sure about the rest, namely evaluating two fields from the same document array







      mongodb mongodb-query aggregation-framework






      share|improve this question















      share|improve this question













      share|improve this question




      share|improve this question








      edited Nov 22 at 17:24









      Anthony Winzlet

      12.8k41039




      12.8k41039










      asked Nov 21 at 15:55









      Yanick Rochon

      33.8k1789158




      33.8k1789158
























          2 Answers
          2






          active

          oldest

          votes

















          up vote
          1
          down vote



          accepted










          You can try below aggregation:



          db.col.aggregate([
          {
          $unwind: "$activities"
          },
          {
          $match: {
          $and: [
          { "activities.timestamp": { $gte: "10000001" } },
          { "activities.timestamp": { $lte: "10000002" } }
          ]
          }
          },
          {
          $sort: {
          "activities.timestamp": -1
          }
          },
          {
          $group: {
          _id: "$_id",
          userId: { $first: "$userId" },
          activities: { $push: "$activities" }
          }
          },
          {
          $addFields: {
          login: { $arrayElemAt: [ { $filter: { input: "$activities", as: "a", cond: { $eq: [ "$$a.status", "login" ] } } } , 0 ] },
          logout: { $arrayElemAt: [ { $filter: { input: "$activities", as: "a", cond: { $eq: [ "$$a.status", "logout" ] } } } , 0 ] }
          }
          },
          {
          $project: {
          _id: 1,
          userId: 1,
          login: { $ifNull: [ "$login.timestamp", null ] },
          logout: { $ifNull: [ "$logout.timestamp", null ] }
          }
          }
          ])


          We need to use $unwind + $sort + $group to make sure that our activities will be sorted by timestamp. After $unwind you can use $match to apply filtering condition. Then you can use $filter with $arrayElemAt to get first (latest) value of filtered array. In the last $project you can explicitly use $ifNull (otherwise JSON key will be skipped if there's no value)






          share|improve this answer























          • I have an issue with this query; the $gte and $lte on the same field only returns one document from the collection.
            – Yanick Rochon
            Nov 22 at 15:05










          • @YanickRochon could you send me the mongoplayground with your data (mongoplayground.net) ?
            – mickl
            Nov 22 at 15:08










          • I have tried the query I have on mongoplayground et it returns the expected result. Yet, the mongo driver I use does not. The version I have is 3.6.4 and mongoplaygroud uses 4.0.3.
            – Yanick Rochon
            Nov 22 at 15:25






          • 1




            Right, I understood the issue; some timestamps are stored as strings, while others as ISODate objects.
            – Yanick Rochon
            Nov 22 at 16:40


















          up vote
          1
          down vote













          You can use below aggregation



          Instead of $unwind use $lte and $gte with the $fitler aggregation.



          db.collection.aggregate([
          { "$project": {
          "userId": 1,
          "login": {
          "$max": {
          "$filter": {
          "input": "$activities",
          "cond": {
          "$and": [
          { "$gte": ["$$this.timestamp", "10000001"] },
          { "$lte": ["$$this.timestamp", "10000004"] },
          { "$lte": ["$$this.status", "login"] }
          ]
          }
          }
          }
          },
          "logout": {
          "$max": {
          "$filter": {
          "input": "$activities",
          "cond": {
          "$and": [
          { "$gte": ["$$this.timestamp", "10000001"] },
          { "$lte": ["$$this.timestamp", "10000004"] },
          { "$lte": ["$$this.status", "logout"] }
          ]
          }
          }
          }
          }
          }}
          ])





          share|improve this answer



















          • 1




            Wouldn't you need to sort activities before fetching $arrayElemAt? Because if the timestamp range is large, and if there are multiple "logout" activities, what guarantees that the most recent one will be returned? (Idem for "login".)
            – Yanick Rochon
            Nov 21 at 20:55






          • 1




            @YanickRochon Updated my answer. You can use $max operator with the timestamp to get the latest record from the array. Now can achieve this with single aggregation stage even.
            – Anthony Winzlet
            Nov 22 at 16:48













          Your Answer






          StackExchange.ifUsing("editor", function () {
          StackExchange.using("externalEditor", function () {
          StackExchange.using("snippets", function () {
          StackExchange.snippets.init();
          });
          });
          }, "code-snippets");

          StackExchange.ready(function() {
          var channelOptions = {
          tags: "".split(" "),
          id: "1"
          };
          initTagRenderer("".split(" "), "".split(" "), channelOptions);

          StackExchange.using("externalEditor", function() {
          // Have to fire editor after snippets, if snippets enabled
          if (StackExchange.settings.snippets.snippetsEnabled) {
          StackExchange.using("snippets", function() {
          createEditor();
          });
          }
          else {
          createEditor();
          }
          });

          function createEditor() {
          StackExchange.prepareEditor({
          heartbeatType: 'answer',
          convertImagesToLinks: true,
          noModals: true,
          showLowRepImageUploadWarning: true,
          reputationToPostImages: 10,
          bindNavPrevention: true,
          postfix: "",
          imageUploader: {
          brandingHtml: "Powered by u003ca class="icon-imgur-white" href="https://imgur.com/"u003eu003c/au003e",
          contentPolicyHtml: "User contributions licensed under u003ca href="https://creativecommons.org/licenses/by-sa/3.0/"u003ecc by-sa 3.0 with attribution requiredu003c/au003e u003ca href="https://stackoverflow.com/legal/content-policy"u003e(content policy)u003c/au003e",
          allowUrls: true
          },
          onDemand: true,
          discardSelector: ".discard-answer"
          ,immediatelyShowMarkdownHelp:true
          });


          }
          });














          draft saved

          draft discarded


















          StackExchange.ready(
          function () {
          StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f53415876%2freturning-a-document-with-two-fields-from-the-same-array-in-mongodb%23new-answer', 'question_page');
          }
          );

          Post as a guest















          Required, but never shown

























          2 Answers
          2






          active

          oldest

          votes








          2 Answers
          2






          active

          oldest

          votes









          active

          oldest

          votes






          active

          oldest

          votes








          up vote
          1
          down vote



          accepted










          You can try below aggregation:



          db.col.aggregate([
          {
          $unwind: "$activities"
          },
          {
          $match: {
          $and: [
          { "activities.timestamp": { $gte: "10000001" } },
          { "activities.timestamp": { $lte: "10000002" } }
          ]
          }
          },
          {
          $sort: {
          "activities.timestamp": -1
          }
          },
          {
          $group: {
          _id: "$_id",
          userId: { $first: "$userId" },
          activities: { $push: "$activities" }
          }
          },
          {
          $addFields: {
          login: { $arrayElemAt: [ { $filter: { input: "$activities", as: "a", cond: { $eq: [ "$$a.status", "login" ] } } } , 0 ] },
          logout: { $arrayElemAt: [ { $filter: { input: "$activities", as: "a", cond: { $eq: [ "$$a.status", "logout" ] } } } , 0 ] }
          }
          },
          {
          $project: {
          _id: 1,
          userId: 1,
          login: { $ifNull: [ "$login.timestamp", null ] },
          logout: { $ifNull: [ "$logout.timestamp", null ] }
          }
          }
          ])


          We need to use $unwind + $sort + $group to make sure that our activities will be sorted by timestamp. After $unwind you can use $match to apply filtering condition. Then you can use $filter with $arrayElemAt to get first (latest) value of filtered array. In the last $project you can explicitly use $ifNull (otherwise JSON key will be skipped if there's no value)






          share|improve this answer























          • I have an issue with this query; the $gte and $lte on the same field only returns one document from the collection.
            – Yanick Rochon
            Nov 22 at 15:05










          • @YanickRochon could you send me the mongoplayground with your data (mongoplayground.net) ?
            – mickl
            Nov 22 at 15:08










          • I have tried the query I have on mongoplayground et it returns the expected result. Yet, the mongo driver I use does not. The version I have is 3.6.4 and mongoplaygroud uses 4.0.3.
            – Yanick Rochon
            Nov 22 at 15:25






          • 1




            Right, I understood the issue; some timestamps are stored as strings, while others as ISODate objects.
            – Yanick Rochon
            Nov 22 at 16:40















          up vote
          1
          down vote



          accepted










          You can try below aggregation:



          db.col.aggregate([
          {
          $unwind: "$activities"
          },
          {
          $match: {
          $and: [
          { "activities.timestamp": { $gte: "10000001" } },
          { "activities.timestamp": { $lte: "10000002" } }
          ]
          }
          },
          {
          $sort: {
          "activities.timestamp": -1
          }
          },
          {
          $group: {
          _id: "$_id",
          userId: { $first: "$userId" },
          activities: { $push: "$activities" }
          }
          },
          {
          $addFields: {
          login: { $arrayElemAt: [ { $filter: { input: "$activities", as: "a", cond: { $eq: [ "$$a.status", "login" ] } } } , 0 ] },
          logout: { $arrayElemAt: [ { $filter: { input: "$activities", as: "a", cond: { $eq: [ "$$a.status", "logout" ] } } } , 0 ] }
          }
          },
          {
          $project: {
          _id: 1,
          userId: 1,
          login: { $ifNull: [ "$login.timestamp", null ] },
          logout: { $ifNull: [ "$logout.timestamp", null ] }
          }
          }
          ])


          We need to use $unwind + $sort + $group to make sure that our activities will be sorted by timestamp. After $unwind you can use $match to apply filtering condition. Then you can use $filter with $arrayElemAt to get first (latest) value of filtered array. In the last $project you can explicitly use $ifNull (otherwise JSON key will be skipped if there's no value)






          share|improve this answer























          • I have an issue with this query; the $gte and $lte on the same field only returns one document from the collection.
            – Yanick Rochon
            Nov 22 at 15:05










          • @YanickRochon could you send me the mongoplayground with your data (mongoplayground.net) ?
            – mickl
            Nov 22 at 15:08










          • I have tried the query I have on mongoplayground et it returns the expected result. Yet, the mongo driver I use does not. The version I have is 3.6.4 and mongoplaygroud uses 4.0.3.
            – Yanick Rochon
            Nov 22 at 15:25






          • 1




            Right, I understood the issue; some timestamps are stored as strings, while others as ISODate objects.
            – Yanick Rochon
            Nov 22 at 16:40













          up vote
          1
          down vote



          accepted







          up vote
          1
          down vote



          accepted






          You can try below aggregation:



          db.col.aggregate([
          {
          $unwind: "$activities"
          },
          {
          $match: {
          $and: [
          { "activities.timestamp": { $gte: "10000001" } },
          { "activities.timestamp": { $lte: "10000002" } }
          ]
          }
          },
          {
          $sort: {
          "activities.timestamp": -1
          }
          },
          {
          $group: {
          _id: "$_id",
          userId: { $first: "$userId" },
          activities: { $push: "$activities" }
          }
          },
          {
          $addFields: {
          login: { $arrayElemAt: [ { $filter: { input: "$activities", as: "a", cond: { $eq: [ "$$a.status", "login" ] } } } , 0 ] },
          logout: { $arrayElemAt: [ { $filter: { input: "$activities", as: "a", cond: { $eq: [ "$$a.status", "logout" ] } } } , 0 ] }
          }
          },
          {
          $project: {
          _id: 1,
          userId: 1,
          login: { $ifNull: [ "$login.timestamp", null ] },
          logout: { $ifNull: [ "$logout.timestamp", null ] }
          }
          }
          ])


          We need to use $unwind + $sort + $group to make sure that our activities will be sorted by timestamp. After $unwind you can use $match to apply filtering condition. Then you can use $filter with $arrayElemAt to get first (latest) value of filtered array. In the last $project you can explicitly use $ifNull (otherwise JSON key will be skipped if there's no value)






          share|improve this answer














          You can try below aggregation:



          db.col.aggregate([
          {
          $unwind: "$activities"
          },
          {
          $match: {
          $and: [
          { "activities.timestamp": { $gte: "10000001" } },
          { "activities.timestamp": { $lte: "10000002" } }
          ]
          }
          },
          {
          $sort: {
          "activities.timestamp": -1
          }
          },
          {
          $group: {
          _id: "$_id",
          userId: { $first: "$userId" },
          activities: { $push: "$activities" }
          }
          },
          {
          $addFields: {
          login: { $arrayElemAt: [ { $filter: { input: "$activities", as: "a", cond: { $eq: [ "$$a.status", "login" ] } } } , 0 ] },
          logout: { $arrayElemAt: [ { $filter: { input: "$activities", as: "a", cond: { $eq: [ "$$a.status", "logout" ] } } } , 0 ] }
          }
          },
          {
          $project: {
          _id: 1,
          userId: 1,
          login: { $ifNull: [ "$login.timestamp", null ] },
          logout: { $ifNull: [ "$logout.timestamp", null ] }
          }
          }
          ])


          We need to use $unwind + $sort + $group to make sure that our activities will be sorted by timestamp. After $unwind you can use $match to apply filtering condition. Then you can use $filter with $arrayElemAt to get first (latest) value of filtered array. In the last $project you can explicitly use $ifNull (otherwise JSON key will be skipped if there's no value)







          share|improve this answer














          share|improve this answer



          share|improve this answer








          edited Nov 21 at 17:12

























          answered Nov 21 at 17:07









          mickl

          10.8k51535




          10.8k51535












          • I have an issue with this query; the $gte and $lte on the same field only returns one document from the collection.
            – Yanick Rochon
            Nov 22 at 15:05










          • @YanickRochon could you send me the mongoplayground with your data (mongoplayground.net) ?
            – mickl
            Nov 22 at 15:08










          • I have tried the query I have on mongoplayground et it returns the expected result. Yet, the mongo driver I use does not. The version I have is 3.6.4 and mongoplaygroud uses 4.0.3.
            – Yanick Rochon
            Nov 22 at 15:25






          • 1




            Right, I understood the issue; some timestamps are stored as strings, while others as ISODate objects.
            – Yanick Rochon
            Nov 22 at 16:40


















          • I have an issue with this query; the $gte and $lte on the same field only returns one document from the collection.
            – Yanick Rochon
            Nov 22 at 15:05










          • @YanickRochon could you send me the mongoplayground with your data (mongoplayground.net) ?
            – mickl
            Nov 22 at 15:08










          • I have tried the query I have on mongoplayground et it returns the expected result. Yet, the mongo driver I use does not. The version I have is 3.6.4 and mongoplaygroud uses 4.0.3.
            – Yanick Rochon
            Nov 22 at 15:25






          • 1




            Right, I understood the issue; some timestamps are stored as strings, while others as ISODate objects.
            – Yanick Rochon
            Nov 22 at 16:40
















          I have an issue with this query; the $gte and $lte on the same field only returns one document from the collection.
          – Yanick Rochon
          Nov 22 at 15:05




          I have an issue with this query; the $gte and $lte on the same field only returns one document from the collection.
          – Yanick Rochon
          Nov 22 at 15:05












          @YanickRochon could you send me the mongoplayground with your data (mongoplayground.net) ?
          – mickl
          Nov 22 at 15:08




          @YanickRochon could you send me the mongoplayground with your data (mongoplayground.net) ?
          – mickl
          Nov 22 at 15:08












          I have tried the query I have on mongoplayground et it returns the expected result. Yet, the mongo driver I use does not. The version I have is 3.6.4 and mongoplaygroud uses 4.0.3.
          – Yanick Rochon
          Nov 22 at 15:25




          I have tried the query I have on mongoplayground et it returns the expected result. Yet, the mongo driver I use does not. The version I have is 3.6.4 and mongoplaygroud uses 4.0.3.
          – Yanick Rochon
          Nov 22 at 15:25




          1




          1




          Right, I understood the issue; some timestamps are stored as strings, while others as ISODate objects.
          – Yanick Rochon
          Nov 22 at 16:40




          Right, I understood the issue; some timestamps are stored as strings, while others as ISODate objects.
          – Yanick Rochon
          Nov 22 at 16:40












          up vote
          1
          down vote













          You can use below aggregation



          Instead of $unwind use $lte and $gte with the $fitler aggregation.



          db.collection.aggregate([
          { "$project": {
          "userId": 1,
          "login": {
          "$max": {
          "$filter": {
          "input": "$activities",
          "cond": {
          "$and": [
          { "$gte": ["$$this.timestamp", "10000001"] },
          { "$lte": ["$$this.timestamp", "10000004"] },
          { "$lte": ["$$this.status", "login"] }
          ]
          }
          }
          }
          },
          "logout": {
          "$max": {
          "$filter": {
          "input": "$activities",
          "cond": {
          "$and": [
          { "$gte": ["$$this.timestamp", "10000001"] },
          { "$lte": ["$$this.timestamp", "10000004"] },
          { "$lte": ["$$this.status", "logout"] }
          ]
          }
          }
          }
          }
          }}
          ])





          share|improve this answer



















          • 1




            Wouldn't you need to sort activities before fetching $arrayElemAt? Because if the timestamp range is large, and if there are multiple "logout" activities, what guarantees that the most recent one will be returned? (Idem for "login".)
            – Yanick Rochon
            Nov 21 at 20:55






          • 1




            @YanickRochon Updated my answer. You can use $max operator with the timestamp to get the latest record from the array. Now can achieve this with single aggregation stage even.
            – Anthony Winzlet
            Nov 22 at 16:48

















          up vote
          1
          down vote













          You can use below aggregation



          Instead of $unwind use $lte and $gte with the $fitler aggregation.



          db.collection.aggregate([
          { "$project": {
          "userId": 1,
          "login": {
          "$max": {
          "$filter": {
          "input": "$activities",
          "cond": {
          "$and": [
          { "$gte": ["$$this.timestamp", "10000001"] },
          { "$lte": ["$$this.timestamp", "10000004"] },
          { "$lte": ["$$this.status", "login"] }
          ]
          }
          }
          }
          },
          "logout": {
          "$max": {
          "$filter": {
          "input": "$activities",
          "cond": {
          "$and": [
          { "$gte": ["$$this.timestamp", "10000001"] },
          { "$lte": ["$$this.timestamp", "10000004"] },
          { "$lte": ["$$this.status", "logout"] }
          ]
          }
          }
          }
          }
          }}
          ])





          share|improve this answer



















          • 1




            Wouldn't you need to sort activities before fetching $arrayElemAt? Because if the timestamp range is large, and if there are multiple "logout" activities, what guarantees that the most recent one will be returned? (Idem for "login".)
            – Yanick Rochon
            Nov 21 at 20:55






          • 1




            @YanickRochon Updated my answer. You can use $max operator with the timestamp to get the latest record from the array. Now can achieve this with single aggregation stage even.
            – Anthony Winzlet
            Nov 22 at 16:48















          up vote
          1
          down vote










          up vote
          1
          down vote









          You can use below aggregation



          Instead of $unwind use $lte and $gte with the $fitler aggregation.



          db.collection.aggregate([
          { "$project": {
          "userId": 1,
          "login": {
          "$max": {
          "$filter": {
          "input": "$activities",
          "cond": {
          "$and": [
          { "$gte": ["$$this.timestamp", "10000001"] },
          { "$lte": ["$$this.timestamp", "10000004"] },
          { "$lte": ["$$this.status", "login"] }
          ]
          }
          }
          }
          },
          "logout": {
          "$max": {
          "$filter": {
          "input": "$activities",
          "cond": {
          "$and": [
          { "$gte": ["$$this.timestamp", "10000001"] },
          { "$lte": ["$$this.timestamp", "10000004"] },
          { "$lte": ["$$this.status", "logout"] }
          ]
          }
          }
          }
          }
          }}
          ])





          share|improve this answer














          You can use below aggregation



          Instead of $unwind use $lte and $gte with the $fitler aggregation.



          db.collection.aggregate([
          { "$project": {
          "userId": 1,
          "login": {
          "$max": {
          "$filter": {
          "input": "$activities",
          "cond": {
          "$and": [
          { "$gte": ["$$this.timestamp", "10000001"] },
          { "$lte": ["$$this.timestamp", "10000004"] },
          { "$lte": ["$$this.status", "login"] }
          ]
          }
          }
          }
          },
          "logout": {
          "$max": {
          "$filter": {
          "input": "$activities",
          "cond": {
          "$and": [
          { "$gte": ["$$this.timestamp", "10000001"] },
          { "$lte": ["$$this.timestamp", "10000004"] },
          { "$lte": ["$$this.status", "logout"] }
          ]
          }
          }
          }
          }
          }}
          ])






          share|improve this answer














          share|improve this answer



          share|improve this answer








          edited Nov 22 at 16:47

























          answered Nov 21 at 18:50









          Anthony Winzlet

          12.8k41039




          12.8k41039








          • 1




            Wouldn't you need to sort activities before fetching $arrayElemAt? Because if the timestamp range is large, and if there are multiple "logout" activities, what guarantees that the most recent one will be returned? (Idem for "login".)
            – Yanick Rochon
            Nov 21 at 20:55






          • 1




            @YanickRochon Updated my answer. You can use $max operator with the timestamp to get the latest record from the array. Now can achieve this with single aggregation stage even.
            – Anthony Winzlet
            Nov 22 at 16:48
















          • 1




            Wouldn't you need to sort activities before fetching $arrayElemAt? Because if the timestamp range is large, and if there are multiple "logout" activities, what guarantees that the most recent one will be returned? (Idem for "login".)
            – Yanick Rochon
            Nov 21 at 20:55






          • 1




            @YanickRochon Updated my answer. You can use $max operator with the timestamp to get the latest record from the array. Now can achieve this with single aggregation stage even.
            – Anthony Winzlet
            Nov 22 at 16:48










          1




          1




          Wouldn't you need to sort activities before fetching $arrayElemAt? Because if the timestamp range is large, and if there are multiple "logout" activities, what guarantees that the most recent one will be returned? (Idem for "login".)
          – Yanick Rochon
          Nov 21 at 20:55




          Wouldn't you need to sort activities before fetching $arrayElemAt? Because if the timestamp range is large, and if there are multiple "logout" activities, what guarantees that the most recent one will be returned? (Idem for "login".)
          – Yanick Rochon
          Nov 21 at 20:55




          1




          1




          @YanickRochon Updated my answer. You can use $max operator with the timestamp to get the latest record from the array. Now can achieve this with single aggregation stage even.
          – Anthony Winzlet
          Nov 22 at 16:48






          @YanickRochon Updated my answer. You can use $max operator with the timestamp to get the latest record from the array. Now can achieve this with single aggregation stage even.
          – Anthony Winzlet
          Nov 22 at 16:48




















          draft saved

          draft discarded




















































          Thanks for contributing an answer to Stack Overflow!


          • Please be sure to answer the question. Provide details and share your research!

          But avoid



          • Asking for help, clarification, or responding to other answers.

          • Making statements based on opinion; back them up with references or personal experience.


          To learn more, see our tips on writing great answers.





          Some of your past answers have not been well-received, and you're in danger of being blocked from answering.


          Please pay close attention to the following guidance:


          • Please be sure to answer the question. Provide details and share your research!

          But avoid



          • Asking for help, clarification, or responding to other answers.

          • Making statements based on opinion; back them up with references or personal experience.


          To learn more, see our tips on writing great answers.




          draft saved


          draft discarded














          StackExchange.ready(
          function () {
          StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f53415876%2freturning-a-document-with-two-fields-from-the-same-array-in-mongodb%23new-answer', 'question_page');
          }
          );

          Post as a guest















          Required, but never shown





















































          Required, but never shown














          Required, but never shown












          Required, but never shown







          Required, but never shown

































          Required, but never shown














          Required, but never shown












          Required, but never shown







          Required, but never shown







          Popular posts from this blog

          Trompette piccolo

          Slow SSRS Report in dynamic grouping and multiple parameters

          Simon Yates (cyclisme)