如何在Java中查询MongoDB子文档

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

How to query MongoDb subdocuments in Java

问题

亲爱的MongoDB专家们!我是Mongo的新手,目前正在使用Java处理MongoDB。

我有一个名为“teams”的集合的MongoDB,其示例结构如下:

  1. [
  2. {
  3. "id": "123",
  4. "name": "Dev1",
  5. "employees": [
  6. {"name": "John", "age": 30},
  7. {"name": "Jane", "age": 30}
  8. ]
  9. },
  10. {
  11. "id": "456",
  12. "name": "Dev2",
  13. "employees": [
  14. {"name": "Mike", "age": 30},
  15. {"name": "Oscar", "age": 27}
  16. ]
  17. }
  18. ]

我想要一个查询,返回一个数组,其中包含所有年龄为30岁的员工。所以期望的结果将是:

  1. [
  2. {"name": "John", "age": 30},
  3. {"name": "Jane", "age": 30},
  4. {"name": "Mike", "age": 30}
  5. ]

甚至只获取员工的名字会更好(因为我知道我正在搜索的年龄),如下:

  1. [
  2. {"name": "John"},
  3. {"name": "Jane"},
  4. {"name": "Mike"}
  5. ]

我有一个MongoCollection对象:

  1. MongoCollection<Document> collection = mongoClient
  2. .getDatabase(databaseName)
  3. .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:

  1. {[
  2. {
  3. &quot;id&quot;: &quot;123&quot;,
  4. &quot;name&quot;: &quot;Dev1&quot;,
  5. &quot;employees&quot;: [
  6. {&quot;name&quot;: &quot;John&quot;, &quot;age&quot;: 30},
  7. {&quot;name&quot;: &quot;Jane&quot;, &quot;age&quot;: 30}
  8. ]
  9. },
  10. {
  11. &quot;id&quot;: &quot;456&quot;,
  12. &quot;name&quot;: &quot;Dev2&quot;,
  13. &quot;employees&quot;: [
  14. {&quot;name&quot;: &quot;Mike&quot;, &quot;age&quot;: 30},
  15. {&quot;name&quot;: &quot;Oscar&quot;, &quot;age&quot;: 27}
  16. ]
  17. }
  18. ]}

I want to have a query which returns an array with all employees, that are 30 years old. So the expected result would be:

  1. {[
  2. {&quot;name&quot;: &quot;John&quot;, &quot;age&quot;: 30},
  3. {&quot;name&quot;: &quot;Jane&quot;, &quot;age&quot;: 30},
  4. {&quot;name&quot;: &quot;Mike&quot;, &quot;age&quot;: 30}
  5. ]}

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

  1. {[
  2. {&quot;name&quot;: &quot;John&quot;},
  3. {&quot;name&quot;: &quot;Jane&quot;},
  4. {&quot;name&quot;: &quot;Mike&quot;}
  5. ]}

I have a MongoCollection object:

  1. MongoCollection&lt;Document&gt; collection = mongoClient
  2. .getDatabase(databaseName)
  3. .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 投影进行查找

  1. db.getCollection('teams').find(
  2. {"employees.age": 30},
  3. { "employees": { "$elemMatch": { "age": 30 } }, "_id": 0 }
  4. )

输出格式:

  1. {
  2. "employees": [
  3. {
  4. "name": "John",
  5. "age": 30.0
  6. }
  7. ]
  8. }
  9. {
  10. "employees": [
  11. {
  12. "name": "Mike",
  13. "age": 30.0
  14. }
  15. ]
  16. }

方法二:使用 $unwind 和 $projection 进行聚合和键重命名

  1. db.getCollection('teams').aggregate([
  2. {"$match": {"employees.age": 30}},
  3. {"$unwind": "$employees"},
  4. {"$match": {"employees.age": 30}},
  5. {"$project": {"name": "$employees.name", "_id": 0}}
  6. ])

输出格式:

  1. {
  2. "name": "John"
  3. }
  4. {
  5. "name": "Jane"
  6. }
  7. {
  8. "name": "Mike"
  9. }

方法一可能更快,但需要在应用层进行额外的处理。建议将格式化任务转移到应用服务器上,而不是在数据库本身执行。

方法二可以立即提供格式化的结果,在数据库服务器上同时进行查询和格式化处理。

英文:

Approach 1: Find with $elemMatch projection

  1. db.getCollection(&#39;teams&#39;).find(
  2. {&quot;employees.age&quot;:30},
  3. { &quot;employees&quot;: { &quot;$elemMatch&quot;: { &quot;age&quot;: 30 } },&quot;_id&quot;:0 }
  4. )

Output Format:

  1. {
  2. &quot;employees&quot; : [
  3. {
  4. &quot;name&quot; : &quot;John&quot;,
  5. &quot;age&quot; : 30.0
  6. }
  7. ]
  8. }
  9. {
  10. &quot;employees&quot; : [
  11. {
  12. &quot;name&quot; : &quot;Mike&quot;,
  13. &quot;age&quot; : 30.0
  14. }
  15. ]
  16. }

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

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

Output format:

  1. {
  2. &quot;name&quot; : &quot;John&quot;
  3. }
  4. {
  5. &quot;name&quot; : &quot;Jane&quot;
  6. }
  7. {
  8. &quot;name&quot; : &quot;Mike&quot;
  9. }

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:

确定