mfenniak / rethinkdb-net

A C# / .NET client driver for RethinkDB.
Other
247 stars 37 forks source link

Query Expressions with JObect #222

Closed cecilphillip closed 9 years ago

cecilphillip commented 9 years ago

I have some ReQL that looks something like this

  r.db("tkm_analytics").table("event_items")
    .group(r.row("event_type"))    
    .map(function(event){
      return {
        //date : event('date_created'),
        count: 1,
        today: r.branch(event('date_created').date().eq(r.now().date()),1,0),
        month: r.branch(event('date_created').month().eq(r.now().month()),1,0) 
      }
     })
    .reduce(function(left, right){
      return {
        count: left('count').add(right('count')),
        today: left('today').add(right('today')),
        month: left('month').add(right('month'))
      }
    }).default({count: 0})

Now this far I have been storing my documents using JObjects. So my query objects look like following:

   IDatabaseQuery _db = Query.Db(DEFAULT_DATABASE_NAME);
   ITableQuery<JObject> _table = _db.Table<JObject>(DEFAULT_TABLE_NAME);

I use JObjects because my schemas are very loose with the exception of some core fields. I can't seem to do a group or filter on JObjects. I get an error that pretty much says the expression could not be evaluated, e.g. _table.Group(evt => evt["event_type"]);

Is there another way that I could query/filter on the data? Is there a non generic ITableQuery that I could use ?

mfenniak commented 9 years ago

If you're using a loose schema, you can use an IDictionary<string, object> as your type and expressions will work on a dictionary like you'd expect (see https://github.com/mfenniak/rethinkdb-net/blob/master/rethinkdb-net-test/Integration/NamedValueDictionaryTests.cs#L269 for examples).

I'd generally advise separating the "core fields" and the flexible fields, so that you'd have a schema with typed fields and then an IDictionary<string, object> field that contains all of the loose fields. With this approach, you get C# type safety where you can, and no lost functionality where you have less defined data.

cecilphillip commented 9 years ago

That works. Thanks.

cecilphillip commented 9 years ago

In case anyone want's to know how this map reduce ReSQL query converted into C#, here's what it looks like

            var today = DateTime.Now.Date;
            var query = _table.Group(evt => evt.EventType)
                .Map(e => new
                {
                    count = 1,

                    today = (e.DateCreated.Day == (today.Day) &&
                             e.DateCreated.Month == (today.Month) &&
                             e.DateCreated.Year == (today.Year)) ? 1 : 0,
                    month = (e.DateCreated.Month == (today.Month) &&
                             e.DateCreated.Year == (today.Year)) ? 1 : 0,
                })
                 .Reduce((left, right) => new
                 {
                     count = left.count + right.count,
                     today = left.today + right.today,
                     month = left.month     + right.month
                 }); 

            var result = conn.Run(query);