web-dev-qa-db-ja.com

日数の差がx日である場合のSpringMongoDBクエリドキュメント

2つの日付フィールドを持つコレクションがあり、15日の違いがあるすべてのレコードをクエリしようとしています。

{
   "_id" : "someid",
   "factoryNumber" : 123,
   "factoryName" : "some factory name",
   "visitType" : "audit",
   "personelId" : "somePersonel",
   "lastVisit": ISODate("2018-10-30T00:00:00.000+0000"),
   "acceptedDate" : ISODate("2018-11-16T00:00:00.000+0000")
}

場合によっては、acceptedDateが存在しないため、現在の日付と照らし合わせて評価する必要があります。希望の結果を得るために、春にこのタイプのクエリを作成する方法が完全にはわかりません。

    Criteria.where("acceptedDate"). 
(is 15 days past last visit or current date if last visit not present)
14
jedgard

3.6以降では、新しい演算子$exprを使用する必要があります。これにより、一致クエリ内または通常のクエリで集計式を使用できます。

Jsonクエリを作成し、直接渡すことができます。 $expr は、Springではまだ通常のクエリではサポートされていません。

15日= 15 * 24 * 60 * 60 * 1000 = 1296000000ミリ

Query query = new BasicQuery("{'$expr':{'$gte':[{'$subtract':[{'$ifNull':['$acceptedDate',{'$date':" + System.currentTimeMillis() + "}]},'$lastVisit']},1296000000]}}");
List<Document> results = mongoTemplate.find(query, Document.class);

3.4バージョン

Spring Mongoメソッドを使用する場合は、射影を使用して比較を保持する新しいフィールドを追加し、続いて一致操作と追加の射影を使用して比較フィールドを削除する必要があります。残念ながら $addFields はまだサポートされていないため、AggregationOperationを使用して新しいステージを手動で作成する必要があります。

AggregationOperation addFields = new AggregationOperation() {
    @Override
    public Document toDocument(AggregationOperationContext aggregationOperationContext) {
        Document document = new Document("comp", Document.parse("{'$gte':[{'$subtract':[{'$ifNull':['$acceptedDate', {'$date':" + System.currentTimeMillis() + "}]},'$lastVisit']},1296000000]}}"));      
        return new Document("$addFields", document);
    }
};

Aggregation aggregation = Aggregation.newAggregation(
        addFields,
        Aggregation.match(Criteria.where("comp").is(true))
        Aggregation.project().andExclude("comp");
);

List<Document> results = mongoTemplate.aggregate(aggregation, collection name, Document.class).getMappedResults();

3.2バージョン

AggregationOperation redact = new AggregationOperation() {
    @Override
    public DBObject toDBObject(AggregationOperationContext aggregationOperationContext) {
    Map<String, Object> map = new LinkedHashMap<>();
    map.put("if",  BasicDBObject.parse("{'$gte':[{'$subtract':[{'$ifNull':['$acceptedDate', {'$date':" + System.currentTimeMillis() + "}]},'$lastVisit']},1296000000]}}"));
    map.put("then", "$$KEEP");
    map.put("else", "$$Prune");
    return new BasicDBObject("$redact", new BasicDBObject("$cond", map));
};

Aggregation aggregation = Aggregation.newAggregation(redact);

List<FactoryAcceptance> results = mongoTemplate.aggregate(aggregation, FactoryAcceptance.class, FactoryAcceptance.class).getMappedResults();
10
Sagar Veeram

ドキュメントを取得するには、集約パイプラインを使用する必要があります

  • $ifNull-受け入れられた日付がnullの場合に現在の日付を設定します
  • $addFields-フィールドfromfromDays、およびtoDaysを既存のドキュメントに追加します
  • $redactでフィルタリング
  • $redact-フィールド内で一致してフィルター
  • $project-$addFieldsステージで追加されたフィールドを除外します

mongoクエリ

db.t1.aggregate([
    {$addFields : {
        from : {$ifNull : ["$acceptedDate", new Date()]}
    }},
    {$addFields: {
        fromDays : {$sum : [{$multiply : [365, {$year : "$from"}]}, {$dayOfYear : "$from"}]},
        toDays : {$sum : [{$multiply : [365, {$year : "$lastVisit"}]}, {$dayOfYear : "$lastVisit"}]}
    }},
    { $redact: {
        $cond: {
           if: {$lte : [{$subtract : ["$fromDays", "$toDays"]}, 15]},
           then: "$$DESCEND",
           else: "$$Prune"
         }
       }
    },
    {$project : {from:0, fromDays:0, toDays:0}}
])

サンプルコレクション

> db.t1.find().pretty()
{
        "_id" : "someid",
        "factoryNumber" : 123,
        "factoryName" : "some factory name",
        "visitType" : "audit",
        "personelId" : "somePersonel",
        "lastVisit" : ISODate("2018-10-30T00:00:00Z"),
        "acceptedDate" : ISODate("2018-11-16T00:00:00Z")
}
{
        "_id" : "someotherid",
        "factoryNumber" : 123,
        "factoryName" : "some factory name",
        "visitType" : "audit",
        "personelId" : "somePersonel",
        "lastVisit" : ISODate("2018-10-30T00:00:00Z")
}

最小150日の結果

> db.t1.aggregate([ {$addFields : { from : {$ifNull : ["$acceptedDate", new Date()]} }}, {$addFields: { fromDays : {$sum : [{$multiply : [365, {$year : "$from"}]}, {$dayOfYear : "$from"}]}, toDays : {$sum : [{$multiply : [365, {$year : "$lastVisit"}]}, {$dayOfYear : "$lastVisit"}]} }}, { $redact: {         $cond: {            if: {$lte : [{$subtract : ["$fromDays", "$toDays"]}, 150]},            then: "$$DESCEND",            else: "$$Prune"          }        } }, {$project : {from:0, fromDays:0, toDays:0}} ]).pretty()
{
        "_id" : "someid",
        "factoryNumber" : 123,
        "factoryName" : "some factory name",
        "visitType" : "audit",
        "personelId" : "somePersonel",
        "lastVisit" : ISODate("2018-10-30T00:00:00Z"),
        "acceptedDate" : ISODate("2018-11-16T00:00:00Z")
}
{
        "_id" : "someotherid",
        "factoryNumber" : 123,
        "factoryName" : "some factory name",
        "visitType" : "audit",
        "personelId" : "somePersonel",
        "lastVisit" : ISODate("2018-10-30T00:00:00Z")
}
>

mongoaggregateクエリをspringmongodbクエリに変換します

4
Saravana