0

How can I append a new document to sub-document array on MongoDB with Java?

For exemple, append {tweetId : 456} to the array of documents "tweets":

{
  day : 20170209,
  hours : { 
            hour : 20,
            tweets : {tweetId : 123 }
          }     
}

Desired result:

{
  day : 20170209,
  hours : [ {hour : 20,
             tweets : [{tweetId : 123},{tweetId : 456}]},
            {hour : 21,
             tweets : [{tweetId : 567},{tweetId : 890}]}  
          ]     
}

UPDATE

Sorry, I didn't explain correctly, the tweets document is an Array of tweetsId. I fixed the above example to better understanding.

For example, with a collection with only 2 levels:

{  
   "_id":{  
      "$oid":"589c5a1047e9062f004b84a3"
   },
   "hashtag":"BRASIL",
   "tweets":[  
      {  
         "tweetId":"829661297121845249"
      },
      {  
         "tweetId":"829661278352269313"
      }
   ]
}

I can append a new TweetId to this array with:

collection.updateOne(new Document("hashtag", hashtag),
                    new Document("$push", new Document("tweets", new Document("tweetId", tweetId))));

But when the array is at level 3 (Hours > Tweets > TweetId), I can't find a way to do it correctly.

Hope now it's better explained.

Pedro Grandi
  • 65
  • 1
  • 10
  • I suppose you are trying to implement a time series in Mongo, as explained in [Implementing Time Series in MongoDB](https://dzone.com/articles/implementing-time-series-in-mongodb). However, this is not the right way. If you do not want that the database starts to move your document around memory, documents should be fixed in length. Then, do not use arrays. – riccardo.cardin Feb 09 '17 at 06:31
  • Hi, Riccardo. Actually I'm trying to organize tweets by hour of day. – Pedro Grandi Feb 09 '17 at 12:19
  • Are you sure that the correct document schema is the one you're using? I mean, for an *hashtag* you can have million tweets, that do not feet in a single array. Remember that a document has a maximum size in MongoDB. I suggest you to have a document per tweet, with a list of hashtags. Then, use the Aggregation Framework to work properly with them. – riccardo.cardin Feb 09 '17 at 13:01
  • Hi, Riccardo. I agree that's not the ideal schema for large data, but this is for just a sample and I'd like to understand how to work with nested arrays. Besides of that, I do have another collection of Tweets that contains all information retrieved by Twitter API. But I'll look for this Aggregation Framework to know how it works. Thanks for the tip. – Pedro Grandi Feb 09 '17 at 13:28
  • [Mongo Aggregation Framework](https://docs.mongodb.com/manual/aggregation/) – riccardo.cardin Feb 09 '17 at 13:57

2 Answers2

0

You can't set a dictionary like {tweetId : 123, tweetId : 456},multiple keys is illegal,and this is not an array.

I suggest you redesign your document structure,maybe this document structure is you want:

tweets : [
{
    tweetID:123,
    text:"Hello",
    date:"2017-01-31-09-01-01"
    },
{
    tweetID:456,
    text:"Hi",
    date:"2017-01-31-09-01-01"
    }
]

To append element to array,you can use $push:

The $push operator appends a specified value to an array.

You can download MongoDB Java Driver and then read the java doc and have a try with java.

When you get stuck ,try to read the doc carefully and google it,if it still doesn't work,please show the specific piece of code that's not working.

Hope this helps.

McGrady
  • 10,869
  • 13
  • 47
  • 69
  • Hi, McGrady. Thanks for your answer. What I'm trying to do is create a collection with all tweetIds per hour of the day. – Pedro Grandi Feb 09 '17 at 12:18
  • @PedroGrandi Please read the MongoDB doc,also you can check out [mongodb push in nested array](http://stackoverflow.com/questions/27874469/mongodb-push-in-nested-array).Have a try. – McGrady Feb 09 '17 at 12:21
  • I read the doc and google it a lot, that's how I got to push new documents into an array when it is at level 2 (like the hashtag example). But the problem is when the array is at level 3 (like the day > hour > tweets>. – Pedro Grandi Feb 09 '17 at 13:00
0

with the tip sent by Riccardo, I look how to use the aggregation function and was able to get the result that I needed without creating a collection for tweets by hour.

I used the collection that had all the tweets with its details, and with the function below, was able to retrieve the data:

tweetsCol.aggregate([
                     {$group: {_id : {Date : "$date", Hour : '$hour'}, Total : {$sum : 1}}}
                    ])

My collection of tweets has the following information:

"tweetId" : String,
"userId" : String,
"username" : String,
"followers" : String,
"language" : String,
"fulldate" : String,
"date" : String,
"hour" : String,
"text" : String,
"hashtags" : [{
    "tweetId" : String
 }]

The query result:

[{Date : 20170209,
 hours : [{hour : 21, Total: 45},
          {hour : 22, Total: 22}]},
 {Date : 20170210,
 hours : [{hour : 11, Total: 38},
           hour : 17, Total : 71}]
]
Pedro Grandi
  • 65
  • 1
  • 10