1

I recently started using MongoDB to save data from a project, the basic idea is the following.

On the server side I receive some JSON objects on a WebSocket and store it in the database.

The data I receive looks something like this:

{ 
    {ident: "message_1"},
    data:
    [
        {id: "data_1", value : 10},
        {id: "data_2", value : 20},
        {id: "data_3", value : 40},
        {id: "data_4", value : 60},
        {id: "data_4", value : 60},
    ], 
    timestamp : 12234456
}

And I'm currently saving the entire JSON object in the database.

The server also should handle user http requests where it queries the database for the requested data. The user requests are always for one element of the data array and the timestamp. Thus the server response should look like this:

{ id: "data_1", value : 10, timestamp : 12234456}

I tried using db.collection.find with $elemMatch but my output still contains the data array and the desired element.

{
    data: 
    [{
        id: "data_1",
        value: 10
    }],
   timestamp : 12234456
}

So my question is if there's any possibility to query the database and return only the desired element of ´data´ array combined with the timestamp or I'll need re-create the response JSON object after reading the database.

Kind regards.

2 Answers 2

2

Welcome to the mongo world. You can easily achieve this with aggregations

  • $uwnind to deconstruct the array
  • $match to get the desire value
  • $addFields to add new field to the object
  • $replaceRoot to make the object as root

Here is the code

db.collection.aggregate([
  { "$unwind": "$data" },
  { "$match": { "data.id": "data_1" } },
  { "$addFields": { "data.timestamp": "$timestamp" } },
  { "$replaceRoot": { "newRoot": "$data" } }
])

Working Mongo playground

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

2 Comments

Thanks @varman for the quick reply, I've only use MySQL and now I'm into the mongo world, its been a lot of fun so far, I have a follow up question. Do you have an idea of the overall processing time of executing the ´aggregate´ function bellow compared to the ´find´, lets say i have 100.000 entries or 1.000.000 (what I expect to get over time) will this take a lot of time to process it? (by a lot a mean over 30s to 1m) I'm asking as a way to see if I should perhaps change anything
Few aggregation stages are expensive like unwind, lookup when you do large amount of data . I hope you are looking for explain() in aggregation framework, which provides some helpful information. Please go through stackoverflow.com/questions/12702080/… . But when you optimize the pipelines, the performance will be so fast. Just ping me if you have any aggregation problem, i will try my best to solve. Aggregations are so fun... starting struggles.. but u can catch up easily. I also was in MySQL
0

Although @varman answer is correct for the question, to better match my case where the array data will have a lot of elements (over 100), as @varman in the comment ´unwind´ can be expensive specially when the array contains loads of elements. So the ideal case I would prefer doing the ´unwind´ when the array only contains de desired element, to achieve that I changed the orders to the following:

  • Use "$match To get only the documents with the desired data element
{ "$match": { "data.id": "data_1" } }
  • Use $project and $filter to filter out the unwanted elements from data
   $project: {
      data: {
        $filter: {
          input: "$data",
          as: "data",
          cond: {$eq: ["$$data.id", "data_1"]}
        }
      },
      "timestamp": 1,
      "_id": 0
    }
  • Now add the timestamp field as in the correct answer
  { $addFields: {"data.timestamp": "$timestamp"} }
  • Use unwind to deconstructs data array field from the input documents to output a document for each element.
  {
    $unwind: "$data"
  }
  • Then use $replaceRoot replaces the input document with the data fields.
{"$replaceRoot": {"newRoot": "$data"}} 

Hope this will be usefull to anyone needing to do the same, and if you have any recommendation/improvements on my current setup please I'm in for advices as I'm new to MongoDB.

Running example Mongo Playground

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.