public object Get(POIs request)
        {
            // Try to get the page limit parameter
            int pageLimit = 10;
            if (!request.Limit.IsNullOrEmpty())
            {
              pageLimit = int.Parse(request.Limit);
            }

            // Try to get the offset
            int skipResults = 0;
            if (!request.Offset.IsNullOrEmpty())
            {
              // If pagelimit is -1, skip parameters skips unitary elements
              skipResults = int.Parse(request.Offset) * ((pageLimit != -1) ? pageLimit : 1);
            }

            if (!request.Id.IsNullOrEmpty())
            {
                var objectID = ObjectId.Parse(request.Id);

                var poi = MongoDb.POIs.FindOneById(objectID);

                if (poi == null)
                {
                  base.Response.StatusCode = (int)HttpStatusCode.NotFound;
                  return "POI " + request.Id + " not found";
                }

                // Simple request by id
                if (request.Relation.IsNullOrEmpty())
                {
                  return BuildPOI(MongoDb.POICategories, poi, false);
                }

                if (request.Relation == "parent")
                {
                  MongoCursor<poi> parentPois = MongoDb.POIs.Find(Query.And(Query.EQ("link.term", "child"), Query.EQ("link.id",objectID)));
                  POISResponse parentResponse = new POISResponse();

                  foreach (poi p in parentPois.DistinctBy(d => d._id))
                  {
                    poi tmpPoi = BuildPOI(MongoDb.POICategories, p, false);

                    if(tmpPoi != null)
                      parentResponse.poi.Add(tmpPoi);
                  }

                  if (pageLimit != -1)
                    parentResponse.poi = parentResponse.poi.Skip(skipResults).Take(pageLimit).ToList();
                  else
                    parentResponse.poi = parentResponse.poi.Skip(skipResults).ToList();

                  return parentResponse;
                }

                if (request.Relation == "child")
                {

                  POISResponse childResponse = new POISResponse();

                  if(poi.link.IsNullOrEmpty())
                    return childResponse;

                  foreach (var link in poi.link)
                  {
                    if (link.term != "child")
                      continue;

                    if (ObjectId.TryParse(link.id, out objectID))
                    {
                      poi = MongoDb.POIs.FindOneById(objectID);

                      if (poi != null)
                        childResponse.poi.Add(BuildPOI(MongoDb.POICategories, poi, false));
                    }
                  }

                  if (pageLimit != -1)
                    childResponse.poi = childResponse.poi.Skip(skipResults).Take(pageLimit).ToList();
                  else
                    childResponse.poi = childResponse.poi.Skip(skipResults).ToList();

                  return childResponse;
                }

                if (request.Relation == "events")
                {
                  MongoCursor<@event> events = MongoDb.Events.Find(Query.EQ("location.relationship.targetPOI", objectID));
                  EventsResponse eventResponse = new EventsResponse();

                  if(events != null)
                    foreach (@event ev in events)
                    {
                      @event completeEvent = EventService.BuildEvent(MongoDb.EventCategories, MongoDb.POIs, ev);

                      if(completeEvent != null)
                        [email protected](completeEvent);
                    }

                  if (pageLimit != -1)
                    eventResponse.@event = [email protected](skipResults).Take(pageLimit).ToList();
                  else
                    eventResponse.@event = [email protected](skipResults).ToList();

                  return eventResponse;
                }

                if (request.Relation == "routes")
                {
                  MongoCursor<route> routes = MongoDb.Routes.Find(Query.EQ("pois.location.relationship.targetPOI", objectID));
                  RoutesResponse routeResponse = new RoutesResponse();

                  if(routes != null)
                    foreach(route rt in routes)
                    {
                      route completeRoute = RouteService.BuildRoute(MongoDb.RouteCategories, MongoDb.POIs, rt, false);

                      if(completeRoute != null)
                        routeResponse.routes.Add(completeRoute);
                    }

                  if (pageLimit != -1)
                    routeResponse.routes = routeResponse.routes.Skip(skipResults).Take(pageLimit).ToList();
                  else
                    routeResponse.routes = routeResponse.routes.Skip(skipResults).ToList();

                  return routeResponse;
                }

                base.Response.StatusCode = (int)HttpStatusCode.BadRequest;
                return "Invalid relation: " + request.Relation;
            }

            List<IMongoQuery> queries = new List<IMongoQuery>();

            //Category
            if (!request.Category.IsNullOrEmpty())
            {
                List<IMongoQuery> categoriesList = new List<IMongoQuery>();

                foreach (string category in request.Category.Split(new[] { ',' }, StringSplitOptions.RemoveEmptyEntries))
                {
                    var catsTofind = MongoDb.POICategories.Find(
                      Query.And(
                        Query.EQ("term", "category"),
                        Query.Matches("label.value", new BsonRegularExpression(".*" + category + ".*", "-i")),
                        Query.Or(Query.NotExists("deleted"), Query.GT("deleted", BsonValue.Create(DateTime.UtcNow)))
                      )
                    );
                    categoriesList.AddRange(catsTofind.Select(category1 => Query.Or(new[] { Query.EQ("categoryIDs", category1._id) })));
                }

                if (categoriesList.Count > 0)
                    queries.Add(Query.Or(categoriesList));
                else
                {
                    // If no category was found, we can already reply a empty response...
                    return new POISResponse();
                }
            }

            QueryDocument qDoc = new QueryDocument();

            if (request.Deleted.IsNullOrEmpty())
            {
              queries.Add(Query.Or(Query.NotExists("deleted"), Query.GT("deleted", BsonValue.Create(DateTime.UtcNow))));
            }

            //Tag
            if (!request.Tag.IsNullOrEmpty())
            {
                queries.Add(Query.And(request.Tag.Split(new[] { ',' }, StringSplitOptions.RemoveEmptyEntries).Select(tag => Query.Or(new[] { Query.EQ("tags", tag) }))));
            }

            //Relation
            if (!request.Relation.IsNullOrEmpty())
            {
                queries.Add(Query.And(request.Relation.Split(new[] { ',' }, StringSplitOptions.RemoveEmptyEntries).Select(rel => Query.Or(new[] { Query.EQ("location.relationship.targetPOI", rel) }))));
            }

            //Minimal
            if (!request.Minimal.IsNullOrEmpty())
            {
                queries.AddRange(request.Minimal.Split(new[] { ',' }, StringSplitOptions.RemoveEmptyEntries).Select(word => Query.And(Query.Matches("label.value", "/.*" + word + ".*/i"))));
            }
            else if (!request.Complete.IsNullOrEmpty())
            {
                queries.AddRange(request.Complete.Split(new[] { ',' }, StringSplitOptions.RemoveEmptyEntries).Select(word => Query.And(Query.Matches("label.value", "/.*" + word + ".*/i"))));
            }

            if (!string.IsNullOrEmpty(request.Coords))
            {
                qDoc.AddRange(Utilities.GetGeoIntersect(request.Coords).ToBsonDocument());
            }

            if (queries.Count > 0)
                qDoc.AddRange(Query.And(queries).ToBsonDocument());

            MongoCursor<poi> pois = MongoDb.POIs.Find(qDoc);
            POISResponse response = new POISResponse();

            bool minimal = !request.Minimal.IsNullOrEmpty();
            foreach (var p in pois.DistinctBy(d => d._id))
            {
              poi tmpPoi = BuildPOI(MongoDb.POICategories, p, minimal);

              if(tmpPoi != null)
                response.poi.Add(tmpPoi);
            }

            if (pageLimit != -1)
              response.poi = response.poi.Skip(skipResults).Take(pageLimit).ToList();
            else
              response.poi = response.poi.Skip(skipResults).ToList();

            return response;
        }
        public object Get(Events request)
        {
            if (!request.Id.IsNullOrEmpty())
            {
                var objectID = ObjectId.Parse(request.Id);

                var ev = MongoDb.Events.FindOneById(objectID);

                return BuildEvent(MongoDb.EventCategories, MongoDb.POIs, ev);
            }

            List<IMongoQuery> queries = new List<IMongoQuery>();

            //Category
            if (!request.Category.IsNullOrEmpty())
            {
                List<IMongoQuery> categoriesList = new List<IMongoQuery>();

                foreach (string category in request.Category.Split(new[] { ',' }, StringSplitOptions.RemoveEmptyEntries))
                {
                    var catsTofind = MongoDb.EventCategories.Find(
                      Query.And(
                        Query.EQ("term", "category"),
                        Query.Matches("label.value", new BsonRegularExpression(".*" + category + ".*", "-i")),
                        Query.Or(Query.NotExists("deleted"), Query.GT("deleted", BsonValue.Create(DateTime.UtcNow)))
                      )
                    );
                    categoriesList.AddRange(catsTofind.Select(category1 => Query.Or(new[] { Query.EQ("categoryIDs", category1._id) })));
                }

                if (categoriesList.Count > 0)
                    queries.Add(Query.Or(categoriesList));
                else
                {
                    return new EventsResponse();
                }
            }

            //Tag
            if (!request.Tag.IsNullOrEmpty())
            {
                queries.Add(Query.And(request.Tag.Split(new[] { ',' }, StringSplitOptions.RemoveEmptyEntries).Select(tag => Query.Or(new[] { Query.EQ("tags", tag) }))));
            }

            //Search
            if (!request.Name.IsNullOrEmpty())
            {
                queries.Add(Query.And(Query.Matches("label.value", "/.*" + request.Name + ".*/i")));
            }

            //Time
            if (!request.Time.IsNullOrEmpty())
            {
                string[] dates = request.Time.Split(' ');

                if (dates.Length == 2)
                {
                    DateTime start = DateTime.Parse(dates[0], null, DateTimeStyles.RoundtripKind);
                    DateTime end = DateTime.Parse(dates[1], null, DateTimeStyles.RoundtripKind);

                    //queries.Add(Query.And(Query.GTE("Start", start), Query.LTE("End", end)));
                    queries.Add(Query.And(Query.GTE("End", start), Query.LTE("Start", end)));
                }
            }

            QueryDocument qDoc = new QueryDocument();

            queries.Add(Query.Or(Query.NotExists("deleted"), Query.GT("deleted", BsonValue.Create(DateTime.UtcNow))));
            qDoc.AddRange(Query.And(queries).ToBsonDocument());

            MongoCursor<@event> events = MongoDb.Events.Find(qDoc);

            List<@event> finalEvents = events.ToList();

            if (!string.IsNullOrEmpty(request.Coords))
            {
                finalEvents = new List<@event>();

                var validPois = MongoDb.POIs.Find(Utilities.GetGeoIntersect(request.Coords)).ToList();

                foreach (var ev in events.Where(e => e.location != null && e.location.relationship != null && e.location.relationship.Any()))
                {
                    var rel = ev.location.relationship.AsQueryable().FirstOrDefault(w => w.term == "within" || w.term == "equals");
                    if (rel != null)
                    {
                        if (validPois.Any(a => a._id == rel.targetPOI))
                        {
                            finalEvents.Add(ev);
                        }
                    }
                }
            }

            /*
            if (!request.Show.IsNullOrEmpty())
            {
                int start = int.Parse(request.Show.SplitOnFirst(',')[0]);
                int end = int.Parse(request.Show.SplitOnFirst(',')[1]);

                finalEvents = finalEvents.Skip(start).Take(end - start).ToList();
            }
            */

            int pageLimit = 10;
            if (!request.Limit.IsNullOrEmpty())
            {
              pageLimit = int.Parse(request.Limit);
            }

            int skipResults = 0;
            if (!request.Offset.IsNullOrEmpty())
            {
              skipResults = int.Parse(request.Offset) * ((pageLimit != -1) ? pageLimit : 1);
            }

            if (pageLimit != -1)
              finalEvents = finalEvents.Skip(skipResults).Take(pageLimit).ToList();
            else
              finalEvents = finalEvents.Skip(skipResults).ToList();

            EventsResponse response = new EventsResponse();
            foreach (var p in finalEvents)
            {
              @event e = BuildEvent(MongoDb.EventCategories, MongoDb.POIs, p);

                if (e != null)
                    [email protected](e);
            }

            return response;
        }