如何在Java中查询MongoDB子文档

huangapple go评论67阅读模式
英文:

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:

{[
  {
    &quot;id&quot;: &quot;123&quot;,
    &quot;name&quot;: &quot;Dev1&quot;,
    &quot;employees&quot;: [
      {&quot;name&quot;: &quot;John&quot;, &quot;age&quot;: 30},
      {&quot;name&quot;: &quot;Jane&quot;, &quot;age&quot;: 30}
    ]
  },
  {
    &quot;id&quot;: &quot;456&quot;,
    &quot;name&quot;: &quot;Dev2&quot;,
    &quot;employees&quot;: [
      {&quot;name&quot;: &quot;Mike&quot;, &quot;age&quot;: 30},
      {&quot;name&quot;: &quot;Oscar&quot;, &quot;age&quot;: 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:

{[
  {&quot;name&quot;: &quot;John&quot;, &quot;age&quot;: 30},
  {&quot;name&quot;: &quot;Jane&quot;, &quot;age&quot;: 30},
  {&quot;name&quot;: &quot;Mike&quot;, &quot;age&quot;: 30}
]}

It would be even better to only get the employees name (since I know the age I searched for), like:

{[
  {&quot;name&quot;: &quot;John&quot;},
  {&quot;name&quot;: &quot;Jane&quot;},
  {&quot;name&quot;: &quot;Mike&quot;}
]}

I have a MongoCollection object:

MongoCollection&lt;Document&gt; collection = mongoClient
    .getDatabase(databaseName)
    .getCollection(&quot;teams&quot;)

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(&#39;teams&#39;).find(
      {&quot;employees.age&quot;:30},
      { &quot;employees&quot;: { &quot;$elemMatch&quot;: { &quot;age&quot;: 30 } },&quot;_id&quot;:0 } 
)

Output Format:

{
    &quot;employees&quot; : [ 
        {
            &quot;name&quot; : &quot;John&quot;,
            &quot;age&quot; : 30.0
        }
    ]
}


{
    &quot;employees&quot; : [ 
        {
            &quot;name&quot; : &quot;Mike&quot;,
            &quot;age&quot; : 30.0
        }
    ]
}

Approach 2: Aggregate with $unwind and key renaming using $projection

db.getCollection(&#39;teams&#39;).aggregate([
       {&quot;$match&quot;: {&quot;employees.age&quot;:30}} ,  
       {&quot;$unwind&quot;:  &quot;$employees&quot;},
       {&quot;$match&quot;: {&quot;employees.age&quot;:30}} ,
       {&quot;$project&quot;: {&quot;name&quot;: &quot;$employees.name&quot;,&quot;_id&quot;:0}}
])

Output format:

{
    &quot;name&quot; : &quot;John&quot;
}


{
    &quot;name&quot; : &quot;Jane&quot;
}


{
    &quot;name&quot; : &quot;Mike&quot;
}

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

huangapple
  • 本文由 发表于 2020年6月29日 16:24:20
  • 转载请务必保留本文链接:https://go.coder-hub.com/62633991.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定