- html - 出于某种原因,IE8 对我的 Sass 文件中继承的 html5 CSS 不友好?
- JMeter 在响应断言中使用 span 标签的问题
- html - 在 :hover and :active? 上具有不同效果的 CSS 动画
- html - 相对于居中的 html 内容固定的 CSS 重复背景?
我有一个包含以下形式文档的集合:
{
"_id" : { "$oid" : "67bg............"},
"ID" : "xxxxxxxx",
"senses" : [
{
"word" : "hello",
"lang" : "EN",
"source" : "EN_DICTIONARY"
},
{
"word" : "coche",
"lang" : "ES",
"source" : "ES_DICTIONARY"
},
{
"word" : "bye",
"lang" : "EN",
"source" : "EN_DICTIONARY"
}
]
}
我想查找与 lang=X
和 source=Y
至少一种含义匹配的所有文档,并返回仅包含这些 sense< 的匹配文档
匹配 lang=X
和 source=Y
。
我试过这个:
DBObject sensesQuery = new BasicDBObject();
sensesQuery.put("lang", "EN");
sensesQuery.put("source", "EN_DICTIONARY");
DBObject matchQuery = new BasicDBObject("$elemMatch",sensesQuery);
DBObject fields = new BasicDBOject();
fields.put("senses",matchQuery);
DBObject projection = new BasicDBObject();
projection.put("ID",1)
projection.put("senses",matchQuery);
DBCursor cursor = collection.find(fields,projection)
while(cursor.hasNext()) {
...
}
我的查询适用于匹配文档,但不适用于投影。以上面的文档为例,如果我运行查询,我会得到以下结果:
{
"_id" : { "$oid" : "67bg............"},
"ID" : "xxxxxxxx",
"senses" : [
{
"word" : "hello",
"lang" : "EN",
"source" : "EN_DICTIONARY"
}
]
}
但我想要这个:
{
"_id" : { "$oid" : "67bg............"},
"ID" : "xxxxxxxx",
"senses" : [
{
"word" : "hello",
"lang" : "EN",
"source" : "EN_DICTIONARY"
},
{
"word" : "bye",
"lang" : "EN",
"source" : "EN_DICTIONARY"
}
]
}
我读到了有关聚合的内容,但我不明白如何在 MongoDB Java 驱动程序中使用它。
谢谢
最佳答案
您正在投影和过滤器上使用 $elemMatch
运算符。
来自the docs
The
$elemMatch
operator limits the contents of an field from the query results to contain only the first element matching the$elemMatch
condition.
因此,您所看到的行为是 elemMatch-in-a-projection 的预期行为。
如果您想投影符合过滤条件的文档中 senses
数组中的所有子文档,那么您可以使用:
projection.put("senses", 1);
但是,如果您只想投影那些与您的过滤条件匹配的子文档,那么 $elemMatch
将不适合您,因为它只返回与 $elemMatch< 匹配的第一个元素
条件。您的替代方案是使用聚合框架,例如:
db.collection.aggregate([
// matches documents with a senses sub document having the given lang and source values
{$match: {'senses.lang': 'EN', 'senses.source': 'EN_DICTIONARY'}},
// projects on the senses sub document and filters the output to only return sub
// documents having the given lang and source values
{$project: {
senses: {
$filter: {
input: "$senses",
as: "sense",
cond: { $eq: [ "$$sense.lang", 'EN' ], $eq: [ "$$sense.source", 'EN_DICTIONARY' ] }
}
}
}
}
])
这是使用 MongoDB Java 驱动程序的聚合调用:
Document filter = new Document("senses.lang", "EN").append("senses.source", "EN_DICTIONARY");
DBObject filterExpression = new BasicDBObject();
filterExpression.put("input", "$senses");
filterExpression.put("as", "sense");
filterExpression.put("cond", new BasicDBObject("$and", Arrays.<Object>asList(
new BasicDBObject("$eq", Arrays.<Object>asList("$$sense.lang", "EN")),
new BasicDBObject("$eq", Arrays.<Object>asList("$$sense.source", "EN_DICTIONARY")))
));
BasicDBObject projectionFilter = new BasicDBObject("$filter", filterExpression);
AggregateIterable<Document> documents = collection.aggregate(Arrays.asList(
new Document("$match", filter),
new Document("$project", new Document("senses", projectionFilter))));
for (Document document : documents) {
logger.info("{}", document.toJson());
}
结果输出是:
2017-10-01 17:15:39 [main] INFO c.s.mongo.MongoClientTest - { "_id" : { "$oid" : "59d10cdfc26584cd8b7a0d3b" }, "senses" : [{ "word" : "hello", "lang" : "EN", "source" : "EN_DICTIONARY" }, { "word" : "bye", "lang" : "EN", "source" : "EN_DICTIONARY" }] }
更新 1:以下评论:
After a long period of testing, trying to understand why the query was slow, I noticed that the "$match" parameter does not work, the query should select only records that have at least one sense with source = Y AND lang = X and project them , but the query also returns me documents with senses = []
此过滤器:new Document("senses.lang", "EN").append("senses.source", "EN_DICTIONARY")
不会匹配没有 Senses 的文档
属性也不会匹配具有空 senses
属性的文档。为了验证这一点,我将以下文档添加到我自己的集合中:
{
"_id" : ObjectId("59d72a24c26584cd8b7b70a5"),
"ID" : "yyyyyyyy"
}
{
"_id" : ObjectId("59d72a3ac26584cd8b7b70ae"),
"ID" : "zzzzzzzzz",
"senses" : []
}
重新运行上面的代码,我仍然得到想要的结果。
我怀疑您关于上述代码不起作用的说法要么是误报,要么您正在查询的文档与我一直在使用的示例不同。
为了帮助您自己诊断此问题,您可以...
与其他运营商合作,例如无论有没有 $exists
运算符,$match
阶段的行为都是相同的:
new Document("senses", new BasicDBObject("$exists", true))
.append("senses.lang", new BasicDBObject("$eq", "EN"))
.append("senses.source", new BasicDBObject("$eq", "EN_DICTIONARY"))
删除 $project
阶段以准确查看 $match
阶段生成的内容。
关于java - 使用 $elemMatch 时如何投影第一个子文档以外的内容,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/46513879/
根据 mongodb 文档,$elemMatch 的语法是, t.find( { x : { $elemMatch : { a : 1, b : { $gt : 1 } } } } ) 我试过了,效果
我有以下文件 { "_id" : ObjectId("52da43cd6f0a61e8a5059aaf"), "assignments" : [ {
我正在为我的应用中的项目(产品)进行用户评分(赞/不赞)。 我似乎能够通过对象数组实现我想要的,但我想知道 mongodb 是否提供了一种方法来使用数字数组 (user_ids) 实现这一点。 db.
我有以下文件 { "_id" : ObjectId("52da43cd6f0a61e8a5059aaf"), "assignments" : [ {
我正在为我的应用中的项目(产品)进行用户评分(赞/不赞)。 我似乎能够通过对象数组实现我想要的,但我想知道 mongodb 是否提供了一种方法来使用数字数组 (user_ids) 实现这一点。 db.
这是我的对象: { "_id" : ObjectId("53fdcb6796cb9b9aa86f05b9"), "list" : [ "a", "b" ], "complist" : [ { "a"
我正在尝试查找与条件匹配的数组的最后一个元素,例如,如果我有来自 $elemMatch 的数据页: { _id: 1, students: [ { name: "john", scho
我有以下数据结构 { "_id" : ObjectId("523331359245b5a07b903ccc"), "a" : "a", "b" : [ {
我有一个 unitScores 集合,其中每个文档都有一个 id 和一个文档数组,如下所示: "_id": ObjectId("52134edd5b1c2bb503000001"), "scores"
我的 MongoDB 文档结构如下: {_id: ObjectId("53d760721423030c7e14266f"), fruit: 'apple', vitamins: [ {
考虑以下文档: { "_id" : "ID_01", "code" : ["001", "002", "003"], "Others" : "544554" } 我经历了这个MongoDB
所以,我有一个数据库,其中包含大量文档中的数组。我想使用 $in 找到我的查询与一个或多个数组元素完全匹配的整个文档。 所以,文档结构: { "_id": "76561198045636214",
查询运算符$and的用法有什么逻辑区别吗? db.collection.find({$and: [{"array.field1": "someValue"}, {"array.field2": 3}]
我知道您可以使用 $elemMatch 作为投影来限制子集合数组中的项目。当这样使用它时,它会返回匹配的子文档的所有字段,无论是否也指定了 query projections。 是否可以限制匹配子文档
我有一个像这样的集合(摘要)。 { "id":"summaryid", "locations": [ { "id": "loc1",
我有一个包含以下形式文档的集合: { "_id" : { "$oid" : "67bg............"}, "ID" : "xxxxxxxx", "senses"
我有一个像这样的集合(摘要)。 { "id":"summaryid", "locations": [ { "id": "loc1",
假设我有这样一个文档 { title : 'myTitle', favorites : [{name : 'text', number : 6}, {name : 'other', numbe
我的查询: { 'objects.item.opts1.opts2': { '$elemMatch': [ { name: 'false' } ] } } 返回:数组 opts2 中包含任何内容的任何
如何使用 elemMatch 对 SubDocument 数组进行搜索?我有一个名为 ReportCollection 的文档,其中包含以下元素:- /* 0 */ { "_id" : Obj
我是一名优秀的程序员,十分优秀!