java mongodb 数组查询条件_用Java查询MongoDB字段完全匹配的数组元素

我想查询文档中数组元素的一个/多个匹配字段(也可以包括子文档)。

例如:

我的收藏包括以下文件:

{

"_id": 1,

"index": 1,

"elements":[

{

"name":"test",

"date":"Mon Sep 01 01:00:00 EEST 2014" ,

"tag":1

},

{

"name":"test2",

"date":"Mon Sep 01 01:00:00 EEST 2014",

"tag": 2

},

{

"name":"test",

"date":"Mon Sep 01 02:00:00 EEST 2014",

"tag": 3

}

]

},

{

"_id":2,

"index":2,

"elements":[

{

"name":"test",

"date":"Mon Sep 01 01:00:00 EEST 2014" ,

"tag":1

},

{

"name":"test2",

"date":"Mon Sep 01 01:00:00 EEST 2014",

"tag":2

},

{

"name":"test",

"date":"Mon Sep 01 01:10:00 EEST 2014",

"tag":3

}

]

},

{

"_id": 3,

"index": 3,

"elements": [

{

"name":"test",

"date":"Mon Sep 01 01:00:00 EEST 2014",

"tag":1

},

{

"name":"test2",

"date":"Mon Sep 01 01:00:00 EEST 2014",

"tag":2

},

{

"name":"test",

"date":"Mon Sep 01 01:10:00 EEST 2014",

"tag":3

}

]

}

我希望查询结果返回如下文档:

{

"_id":1,

"index": 1,

"elements":[

{

"name":"test",

"date":"Mon Sep 01 02:00:00 EEST 2014" ,

"tag":3

}

]

}

为此,我写了一个查询

Date dCriteria = new SimpleDateFormat("dd/MM/yy HH:mm:ss").parse("01/09/2014 05:00:00");

Query find = new Query( Criteria.where("index").is(3) );  //To find matching documents

find.fields().elemMatch(

"elements",

Criteria.where("name").is("test").and("date").gte(dCriteria)));

mongotemplate.findOne( find, Document.class );

这意味着在MongoDB shell命令中为:

db.collection.find(

{"index": 3 },

{"elements": {

"$elemMatch": {

"name":"test",

"date": {

"$gte": {"$date":"2014-09-01T02:00:000Z" }

}

}

}

)

但它返回以下结果:

{

"_id": 0,

"index": 0,

"elements":[

{

"name":"test",

"date":"Mon Sep 01 01:00:00 EEST 2014",

"tag":1

}

]

}

可以省略_id和index fileds,但是由于匹配条件,它返回数组的第一个macting元素,匹配" name":" test"或" date"大于等于dCriteria,但是我要匹配两个条件 与此同时。

为此,我必须使用$ elemMatch运算符来查询一个数组元素同时匹配多个字段。 但是我不知道如何在我的投影中使用它的语法。

MongoDB将日期存储为UTC,这通常也是通常存储日期的最佳实践,因为它允许在不计算原始起点的情况下往返于各个时区进行转换。

因此,可以肯定的是,这里的实际日期确实是UTC,但是您传入的是从其他时区构造的值。驱动程序实际上使用时期时间戳序列化BSON请求,并注明"日期" BSON类型。这意味着您的输入现在被时区差异"扭曲"了。在这种情况下,需要3个小时代表UTC,因此转换后的日期比您想象的早3个小时。

如果您具有某个特定时区的日期的源数据,则您首先需要转换此数据,如果要在本地时间显示值,则既要作为输入也要在用户界面中进行转换。

因此,将其转换或构造为UTC:

// org.joda.time as Date constructor is deprecated

Date dCriteria = new DateTime(2014,9,1,1,10,DateTimeZone.UTC).toDate();

Query find = new Query( Criteria.where("index").is(3) );  //To find matching documents

find.fields().elemMatch(

"elements",

Criteria.where("name").is("test").and("date").gte(dCriteria)

);

System.out.println(find);

如果您不确定结果查询的结构,请打印出来以进行常规调试。您确实应该在可以在生产中抑制的日志记录级别执行此操作。

如上所示,这与您引用的shell查询相同,但是您的代码本身并不存在,因为它使用的是本地时间而不是UTC。

您也几乎总是真的想要在查询中而不是在投影中进行元素匹配。一旦将$elemMatch移至语句的查询部分,即可使用位置$运算符来投影获得的"第一"匹配项。这样可以确保当数组中的任何元素都不实际符合您的条件时,您不会得到一个空数组。

嗨,尼尔,实际上我的问题不是日期。我也知道mongo使用UTC格式,不在乎日期。我的问题是查询结果。我可以将$ elemMatch条件放入搜索查询中,也不要在投影前得到空文档。但是问题来自于仅在数组元素内部获得匹配的数组元素。这意味着我应该(不确定)将$ elemMatch与另一个elemMatch运算符配合使用来获取与我的查询匹配的元素,因为这是字段名称和测试。

@ C.Kaya您的问题在于日期。元素错误的原因是因为TimeZone差异的调整时间。您应该能够通过基本完成定义查询结束时所做的事情来判断。记录输出以查看序列化表格。您的代码将不会产生与您向shell发出的查询相同的代码。我在做什么。

我用我在帖子中实际使用的时间编辑了时间格式。以下是我使用过的匹配元素的查询:查询:{" index":1," alarms":{" $ elemMatch":{" name":" Test1"," date":{" $ gte": {" $ date":" 2014-09-01T02:00:00.000Z"}}}}},字段:{" alarms":{" $ elemMatch":{" name":" Test1"," date": {" $ gte":{" $ date":" 2014-09-01T02:00:00.000Z"}}}}},排序:空

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值