我需要检索 MongoDB 的对象,只获取带有筛选后数组项。

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

I need to retrieve MongoDB's object just with filtered's array item

问题

以下是翻译好的内容:

我需要在两个日期范围内从我的MongoDB集合中检索所有文档,并筛选数组中的项目。

这是我的两个文档示例:

{
    "_id": ObjectId("5f18fa823406b7000132d097"),
    "last_date": "22/07/2020 23:48:32",
    "history_dates": [
        "22/07/2020 23:48:32",
        "22/07/2020 00:18:53",
        "23/07/2020 00:49:12",
        "23/07/2020 01:19:30"
    ],
    "hostname": "MyHostname1",
    "ip": "142.0.111.79",
    "component": "C:\\Windows\\System32\\es-ES\\KernelBase.dll.mui",
    "process": "LogonUI.exe",
    "date": "23/07/2020 10:26:04"
}
{
    "_id": ObjectId("5f18fa823406b7000132d098"),
    "last_date": "22/07/2020 23:48:33",
    "history_dates": [
        "22/07/2020 23:48:33",
        "23/07/2020 00:18:53"
    ],
    "hostname": "MyHostName2",
    "ip": "142.0.111.54",
    "component": "C:\\Windows\\System32\\es-ES\\KernelBase.dll.mui",
    "process": "svchost.exe",
    "date": "23/07/2020 10:26:04"
}

我需要在数据库中进行查找(使用Spring Data),以检索相同的对象,但是在收到的两个日期之间筛选“history_dates”数组。

例如,如果我的两个收到的日期是:“23/07/2020”和“24/07/2020”,我希望MongoDB返回以下对象:

{
    "_id": ObjectId("5f18fa823406b7000132d097"),
    "last_date": "22/07/2020 23:48:32",
    "history_dates": [
        "23/07/2020 00:49:12",
        "23/07/2020 01:19:30"
    ],
    "hostname": "MyHostname1",
    "ip": "142.0.111.79",
    "component": "C:\\Windows\\System32\\es-ES\\KernelBase.dll.mui",
    "process": "LogonUI.exe",
    "date": "23/07/2020 10:26:04"
}
{
    "_id": ObjectId("5f18fa823406b7000132d098"),
    "last_date": "22/07/2020 23:48:33",
    "history_dates": [
        "23/07/2020 00:18:53"
    ],
    "hostname": "MyHostName2",
    "ip": "142.0.111.54",
    "component": "C:\\Windows\\System32\\es-ES\\KernelBase.dll.mui",
    "process": "svchost.exe",
    "date": "23/07/2020 10:26:04"
}

我对MongoDB的查询实际上一无所知,我一直在尝试使用Spring Data进行操作,但整周都没有成功。

更新1:

感谢Varman,你知道如何只检索具有非空筛选数组的文档吗?

英文:

I'm needing to retrieve just with two dates, all the documents from my MongoDB's collection, with the filtered items from the array.

This is an example of 2 of my documents;

{
        "_id" : ObjectId("5f18fa823406b7000132d097"),
        "last_date" : "22/07/2020 23:48:32",
        "history_dates" : [
                "22/07/2020 23:48:32",
                "22/07/2020 00:18:53",
                "23/07/2020 00:49:12",
                "23/07/2020 01:19:30"
        ],
        "hostname" : "MyHostname1",
        "ip" : "142.0.111.79",
        "component" : "C:\\Windows\\System32\\es-ES\\KernelBase.dll.mui",
        "process" : "LogonUI.exe",
        "date" : "23/07/2020 10:26:04",
}
{
        "_id" : ObjectId("5f18fa823406b7000132d098"),
        "last_date" : "22/07/2020 23:48:33",
        "history_dates" : [
                "22/07/2020 23:48:33",
                "23/07/2020 00:18:53",
        ],
        "hostname" : "MyHostName2",
        "ip" : "142.0.111.54",
        "component" : "C:\\Windows\\System32\\es-ES\\KernelBase.dll.mui",
        "process" : "svchost.exe",
        "date" : "23/07/2020 10:26:04",
}

I'm needing to make a find to my database (Using Spring Data), to retrieve the same objects, but with the "history_dates"'s array filtered between the 2 dates recieved.

For example, if my 2 recieved dates are: "23/07/2020" and "24/07/2020", I want MongoDB to return the next objects;

{
        "_id" : ObjectId("5f18fa823406b7000132d097"),
        "last_date" : "22/07/2020 23:48:32",
        "history_dates" : [
                "23/07/2020 00:49:12",
                "23/07/2020 01:19:30"
        ],
        "hostname" : "MyHostname1",
        "ip" : "142.0.111.79",
        "component" : "C:\\Windows\\System32\\es-ES\\KernelBase.dll.mui",
        "process" : "LogonUI.exe",
        "date" : "23/07/2020 10:26:04",
}
{
        "_id" : ObjectId("5f18fa823406b7000132d098"),
        "last_date" : "22/07/2020 23:48:33",
        "history_dates" : [
                "23/07/2020 00:18:53"
        ],
        "hostname" : "MyHostName2",
        "ip" : "142.0.111.54",
        "component" : "C:\\Windows\\System32\\es-ES\\KernelBase.dll.mui",
        "process" : "svchost.exe",
        "date" : "23/07/2020 10:26:04",
}

I'm really ignorant about MongoDB's queries, and I have been trying to make this with Spring Data all the week.

UPDATE 1.

Thanks varman, and do you know how can i just retrieve the documents with filtered arrays not empty?

答案1

得分: 1

所以基本上你需要进行过滤。MongoTemplate 提供了许多用于 MongoDB 的操作,如果一些方法在 MongoTemplate 中不存在,我们可以使用 Bson Document 模式。在这种情况下,可以参考这篇文章:将Mongo shell查询转换的技巧

实际上,你需要一个类似下面这样的Mongo查询。可以使用以下其中一种方法,比如 $addFields。你还可以使用 $project$set 等等。在这里,$addFields 会覆盖你的 history_dates。(它也用于向文档中添加新字段)。

{
    $addFields: {
        history_dates: {
            $filter: {
                input: "$history_dates",
                cond: {
                    $and: [
                        {
                            $gt: ["$$this", "23/07/2020"]
                        },
                        {
                            $lt: ["$$this", "24/07/2020"]
                        }
                    ]
                }
            }
        }
    }
}

Mongo Playground 中查看实际效果。

你需要将这个转换为 Spring Data。所以在你的类中用 @Autowired 注入 MongoTemplate。

@Autowired
MongoTemplate mongoTemplate;

方法如下:

public List<Object> filterDates() {
    Aggregation aggregation = Aggregation.newAggregation(
        a -> new Document("$addFields",
            new Document("history_dates",
                new Document("$filter",
                    new Document("input", "$history_dates")
                        .append("cond",
                            new Document("$and",
                                Arrays.asList(
                                    new Document("$gt", Arrays.asList("$$this", "23/07/2020")),
                                    new Document("$lt", Arrays.asList("$$this", "24/07/2020"))
                                )
                            )
                        )
                )
            )
        )
    ).withOptions(AggregationOptions.builder().allowDiskUse(Boolean.TRUE).build());
    
    return mongoTemplate.aggregate(aggregation, mongoTemplate.getCollectionName(YOUR_CLASS.class), Object.class).getMappedResults();
}

MongoTemplate 并不提供 $addFields$filter 的添加方法。所以我们只能使用 bson document 模式。我没有在 Spring 中测试过这个。

英文:

So basically you need to do filter. MongoTemplate offers a lot of operation for mongodb, if some methods don't exist in MongoTemplate, we can go with Bson Document pattern. In that case, try this article: Trick to covert mongo shell query.

Actually you need a Mongo query something like following. Using $addFields one of the methods shown below. But you can use $project, $set etc. Here $addFields overwrites your history_dates. (It uses to add new fields to document too).

{
    $addFields: {
        history_dates: {
            $filter: {
                input: &quot;$history_dates&quot;,
                cond: {
                    $and: [{
                            $gt: [&quot;$$this&quot;, &quot;23/07/2020&quot;]
                        },
                        {
                            $lt: [&quot;$$this&quot;, &quot;24/07/2020&quot;]
                        }
                    ]
                }
            }
        }
    }
}

Working Mongo playground.

You need to convert this into spring data. So @Autowired the MongoTemplate in you class.

 @Autowired
    MongoTemplate mongoTemplate;

The method is,

public List&lt;Object&gt; filterDates(){

	Aggregation aggregation = Aggregation.newAggregation(
		a-&gt;new Document(&quot;$addFields&quot;,
			new Document(&quot;history_dates&quot;,
				new Document(&quot;$filter&quot;,
					new Document(&quot;input&quot;,&quot;$history_dates&quot;)
					.append(&quot;cond&quot;,
						new Document(&quot;$and&quot;,
							Arrays.asList(
								new Document(&quot;$gt&quot;,Arrays.asList(&quot;$$this&quot;,&quot;23/07/2020&quot;)),
								new Document(&quot;$lt&quot;,Arrays.asList(&quot;$$this&quot;,&quot;24/07/2020&quot;))							
							)
						)
					)
				)
			)		
		)
	).withOptions(AggregationOptions.builder().allowDiskUse(Boolean.TRUE).build());
    return mongoTemplate.aggregate(aggregation, mongoTemplate.getCollectionName(YOUR_CLASS.class), Object.class).getMappedResults();
}

Mongo template doesn't provide add methods for $addFields and $filter. So we just go with bson document pattern. I haven't tested this in Spring.

huangapple
  • 本文由 发表于 2020年7月24日 11:25:54
  • 转载请务必保留本文链接:https://go.coder-hub.com/63066314.html
匿名

发表评论

匿名网友

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

确定