英文:
How to query MongoDb subdocuments in Java
问题
亲爱的MongoDB专家们!我是Mongo的新手,目前正在使用Java处理MongoDB。
我有一个名为“teams”的集合的MongoDB,其示例结构如下:
[
  {
    "id": "123",
    "name": "Dev1",
    "employees": [
      {"name": "John", "age": 30},
      {"name": "Jane", "age": 30}
    ]
  },
  {
    "id": "456",
    "name": "Dev2",
    "employees": [
      {"name": "Mike", "age": 30},
      {"name": "Oscar", "age": 27}
    ]
  }
]
我想要一个查询,返回一个数组,其中包含所有年龄为30岁的员工。所以期望的结果将是:
[
  {"name": "John", "age": 30},
  {"name": "Jane", "age": 30},
  {"name": "Mike", "age": 30}
]
甚至只获取员工的名字会更好(因为我知道我正在搜索的年龄),如下:
[
  {"name": "John"},
  {"name": "Jane"},
  {"name": "Mike"}
]
我有一个MongoCollection对象:
MongoCollection<Document> collection = mongoClient
    .getDatabase(databaseName)
    .getCollection("teams");
我的问题是:是否可以从MongoDB中检索出我期望的结果?如果可以,我在集合对象上需要调用哪些操作?
英文:
Dear MongoDb Experts out there! I am new to Mongo and I am currently working with a MongoDb with Java.
Having a MongoDb with a collection called "teams" with the following example structure:
{[
  {
    "id": "123",
    "name": "Dev1",
    "employees": [
      {"name": "John", "age": 30},
      {"name": "Jane", "age": 30}
    ]
  },
  {
    "id": "456",
    "name": "Dev2",
    "employees": [
      {"name": "Mike", "age": 30},
      {"name": "Oscar", "age": 27}
    ]
  }
]}
I want to have a query which returns an array with all employees, that are 30 years old. So the expected result would be:
{[
  {"name": "John", "age": 30},
  {"name": "Jane", "age": 30},
  {"name": "Mike", "age": 30}
]}
It would be even better to only get the employees name (since I know the age I searched for), like:
{[
  {"name": "John"},
  {"name": "Jane"},
  {"name": "Mike"}
]}
I have a MongoCollection object:
MongoCollection<Document> collection = mongoClient
    .getDatabase(databaseName)
    .getCollection("teams")
My question: Is it possible to retrieve my expected result from the MongoDb? If so, which operations do I have to call on my collection object?
答案1
得分: 0
方法一:使用 $elemMatch 投影进行查找
db.getCollection('teams').find(
      {"employees.age": 30},
      { "employees": { "$elemMatch": { "age": 30 } }, "_id": 0 } 
)
输出格式:
{
    "employees": [ 
        {
            "name": "John",
            "age": 30.0
        }
    ]
}
{
    "employees": [ 
        {
            "name": "Mike",
            "age": 30.0
        }
    ]
}
方法二:使用 $unwind 和 $projection 进行聚合和键重命名
db.getCollection('teams').aggregate([
       {"$match": {"employees.age": 30}},  
       {"$unwind": "$employees"},
       {"$match": {"employees.age": 30}},
       {"$project": {"name": "$employees.name", "_id": 0}}
])
输出格式:
{
    "name": "John"
}
{
    "name": "Jane"
}
{
    "name": "Mike"
}
方法一可能更快,但需要在应用层进行额外的处理。建议将格式化任务转移到应用服务器上,而不是在数据库本身执行。
方法二可以立即提供格式化的结果,在数据库服务器上同时进行查询和格式化处理。
英文:
Approach 1: Find with $elemMatch projection
db.getCollection('teams').find(
      {"employees.age":30},
      { "employees": { "$elemMatch": { "age": 30 } },"_id":0 } 
)
Output Format:
{
    "employees" : [ 
        {
            "name" : "John",
            "age" : 30.0
        }
    ]
}
{
    "employees" : [ 
        {
            "name" : "Mike",
            "age" : 30.0
        }
    ]
}
Approach 2: Aggregate with $unwind and key renaming using $projection
db.getCollection('teams').aggregate([
       {"$match": {"employees.age":30}} ,  
       {"$unwind":  "$employees"},
       {"$match": {"employees.age":30}} ,
       {"$project": {"name": "$employees.name","_id":0}}
])
Output format:
{
    "name" : "John"
}
{
    "name" : "Jane"
}
{
    "name" : "Mike"
}
Approach 1 would be faster, but require additional work at app layer. It is recommended to offload formatting tasks to app servers rather than on db itself.
Approach 2 can instantly give to the formatted results, doing the querying and formatting both in the database servers
专注分享java语言的经验与见解,让所有开发者获益!

评论