9

I have the following data in MongoDB (simplified for what is necessary to my question).

{
    _id: 0,
    actions: [
        {
            type: "insert",
            data: "abc, quite possibly very very large"
        }
    ]
}
{
    _id: 1,
    actions: [
        {
            type: "update",
            data: "def"
        },{
            type: "delete",
            data: "ghi"
        }
    ]
}

What I would like is to find the first action type for each document, e.g.

{_id:0, first_action_type:"insert"}
{_id:1, first_action_type:"update"}

(It's fine if the data structured differently, but I need those values present, somehow.)

EDIT: I've tried db.collection.find({}, {'actions.action_type':1}), but obviously that returns all elements of the actions array.

NoSQL is quite new to me. Before, I would have stored all this in two tables in a relational database and done something like SELECT id, (SELECT type FROM action WHERE document_id = d.id ORDER BY seq LIMIT 1) action_type FROM document d.

4
  • 1
    simply ...actions[0] for collection.find method Commented Oct 4, 2013 at 6:58
  • These documents are large...I looking to use a projection or something to help me get only what I need. Commented Oct 4, 2013 at 7:00
  • you could add indexes Commented Oct 4, 2013 at 7:01
  • In a SO question like this, you should include an attempted solution, in this case a query you have tried, which did not work. Commented Oct 4, 2013 at 7:10

3 Answers 3

12

You can use $slice operator in projection. (but for what you do i am not sure that the order of the array remain the same when you update it. Just to keep in mind))

db.collection.find({},{'actions':{$slice:1},'actions.type':1})
Sign up to request clarification or add additional context in comments.

Comments

2

Using the $arrayElemAt operator is actually the most elegant way, although the syntax may be unintuitive:

db.collection.aggregate([
  { $project: {first_action_type: {$arrayElemAt: ["$actions.type", 0]}
])

Comments

1

You can also use the Aggregation Pipeline introduced in version 2.2:

db.collection.aggregate([
  { $unwind: '$actions' },
  { $group: { _id: "$_id", first_action_type: { $first: "$actions.type" } } }
])

2 Comments

It will give back the whole array, there is a need for an unwind before the group. like this: db.collection.aggregate([ { $unwind: '$actions' }, { $group: { _id: "$_id", first_action_type: { $first: "$actions.type"} } } ])
@PaulDraper Sorry had a typo. Fixed, you can try now :)

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.