MongoDB - Query on the last element of an array?

2019-01-09 09:34发布

I know that MongoDB supports the syntax find{array.0.field:"value"}, but I specifically want to do this for the last element in the array, which means I don't know the index. Is there some kind of operator for this, or am I out of luck?

EDIT: To clarify, I want find() to only return documents where a field in the last element of an array matches a specific value.

7条回答
混吃等死
2楼-- · 2019-01-09 09:56

Version 3.6 use aggregation to achieve the same.

db.getCollection('deviceTrackerHistory').aggregate([
   {
     $match:{clientId:"12"}
   },
   {
     $project:
      {
         deviceId:1,
         recent: { $arrayElemAt: [ "$history", -1 ] }
      }
   }
])
查看更多
beautiful°
3楼-- · 2019-01-09 09:59

use $slice.

db.collection.find( {}, { array_field: { $slice: -1 } } )

Editing: You can make use of { <field>: { $elemMatch: { <query1>, <query2>, ... } } } to find a match.

But it won't give exactly what you are looking for. I don't think that is possible in mongoDB yet.

查看更多
Animai°情兽
4楼-- · 2019-01-09 10:00

I posted on the official Mongo Google group here, and got an answer from their staff. It appears that what I'm looking for isn't possible. I'm going to just use a different schema approach.

查看更多
放荡不羁爱自由
5楼-- · 2019-01-09 10:00

You can use $expr ( 3.6 mongo version operator ) to use aggregation functions in regular query.

Compare query operators vs aggregation comparison operators.

For scalar arrays

db.col.find({$expr:{$gt:[{$arrayElemAt:["array", -1]}, value]}})

For embedded arrays - Use $arrayElemAt expression with dot notation to project last element.

db.col.find({$expr:{$gt:[{"$arrayElemAt": ["$array.field", 0]}, value]}})

Spring @Query code

@Query("{$expr:{$gt:[{$arrayElemAt:[\"array\", -1]}, ?0]}}")
ReturnType MethodName(ArgType arg);
查看更多
虎瘦雄心在
6楼-- · 2019-01-09 10:01

In 3.2 this is possible. First project so that myField contains only the last element, and then match on myField.

db.collection.aggregate([
   { $project: { id: 1, myField: { $slice: [ "$myField", -1 ] } } },
   { $match: { myField: "myValue" } }
]);
查看更多
霸刀☆藐视天下
7楼-- · 2019-01-09 10:02

Not sure about performance, but this works well for me:

db.getCollection('test').find(
  {
    $where: "this.someArray[this.someArray.length - 1] === 'pattern'"
  }
)
查看更多
登录 后发表回答