Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Find if an element in array has value equal to parent element value

Let's say we have a collection of documents like this one:

{
    "_id" : ObjectId("591c54faf1c1f419a830b9cf"),
    "fingerprint" : "3121733676",
    "screewidth" : "1920",
    "carts" : [ 
        {
            "cartid" : 391796,
            "status" : "New",
            "cart_created" : ISODate("2017-05-17T13:50:37.388Z"),
            "closed" : false,
            "items" : [ 
                {
                    "brandid" : "PIR",
                    "cai" : "2259700"
                }
            ],
            "updatedon" : ISODate("2017-05-17T13:51:24.252Z")
        }, 
        {
            "cartid" : 422907,
            "status" : "New",
            "cart_created" : ISODate("2017-10-23T08:57:06.846Z"),
            "closed" : false,
            "items" : [ 
                {
                    "brandid" : "PIR",
                    "cai" : "IrHlNdGtLfBoTlKsJaRySnM195U"
                }
            ],
            "updatedon" : ISODate("2017-10-23T09:46:08.579Z")
        }
    ],
    "createdon" : ISODate("2016-11-08T10:29:55.120Z"),
    "updatedon" : ISODate("2017-10-23T09:46:29.486Z")
}

How do you extract only the documents where no item in the array $.carts have $.carts.closed set to true and $.carts.updatedon greater than $.updatedon minus 3 days ?

I know how to do find all the documents where no item in the array satisfy the condition $and: [closed: {$eq: true}, {updatedon: {$gt : new ISODate("2017-10-20T20:15:31Z")}}]

But how can you reference the parent element $.updatedon for the comparison?

In plain mongodb shell query language it would aleady be of help.

But I am actually accessing it using c# driver, so my query filter is like this:

FilterDefinition<_visitorData> filter;
filter = Builders<_visitorData>.Filter
  .Gte(f => f.updatedon, DateTime.Now.AddDays(-15));
filter = filter & (
  Builders<_visitorData>.Filter
    .Exists(f => f.carts, false) 
      | !Builders<_visitorData>.Filter.ElemMatch(f => 
        f.carts, c => c.closed && c.updatedon > DateTime.Now.AddDays(-15)
      )
);

How can I replace DateTime.Now.AddDays(-15) with a reference to the document root element updatedon?

like image 487
Max Favilli Avatar asked Oct 24 '17 16:10

Max Favilli


People also ask

How do you check if all the elements in an array have same value?

To check if all values in an array are equal:Use the Array. every() method to iterate over the array. Check if each array element is equal to the first one. The every method only returns true if the condition is met for all array elements.

How do you check if an element is a child of a parent?

Another way to check if the parent element contains any child element is to use the hasChildNodes() method. The hasChildNodes() method returns true if it contains any child element. var parent = document. getElementById("parent"); var child = document.

How do you check if an element is inside another element?

contains() method checks if an element is inside another, and returns a boolean: true if it is, and false if it's not. Call it on the parent element, and pass the element you want to check for in as an argument.

How do you check if an element is a child of a parent using JavaScript?

The Node. contains() method is used to check if a given node is the descendant of another node at any level. The descendant may be directly the child's parent or further up the chain.


2 Answers

You can project the difference of carts.updatedon and updatedon and then filter out the results from this aggregation pipeline.

coll.aggregate([{'$unwind':'$carts'},
                {'$match':{'closed':{'$ne':true}}},
                {'$project':{'carts.cartid':1,'carts.status':1,'carts.cart_created':1,'carts.closed':1,'carts.items':1,'carts.updatedon':1,'updatedon':1,'diff':{'$subtract':['$carts.updatedon','$createdon']}}},
                {'$match': {'diff': {'$gte': 1000 * 60 * 60 * 24 * days}}}])

days = 3 will filter out results more than 3 days difference documents.

I have just given the example of how you can use $subtract to find date difference and filter documents based on that.

like image 91
daemon24 Avatar answered Oct 12 '22 14:10

daemon24


well I was in a similar situation few days back. I tackled it by using Jobject of Newtonsoft.Json. Create a function to return bool which actually process each document take it as input.

  Jobject jOb=Jobject.parse(<Your document string>);
  JArray jAr=JArray.Parse(jOb["carts"]);
  If(jOb["updateon"]=<Your Business Validation>)
  {
     foreach(var item in jAr)
       if(item["closed"]==<Your validation>){ return true}         

   }
 return false;

I hope this helps :) If you handling with any null values in those properties then please use Tryparse and out variable.

like image 33
Debashish Saha Avatar answered Oct 12 '22 14:10

Debashish Saha