public void TestOutMerge()
        {
            var options  = MapReduceOptions.SetOutput(MapReduceOutput.Merge("name"));
            var expected = "{ \"out\" : { \"merge\" : \"name\" } }";

            Assert.AreEqual(expected, options.ToJson());
        }
        public void TestOutMergeWithDatabaseSharded()
        {
            var options  = MapReduceOptions.SetOutput(MapReduceOutput.Merge("database", "name", true));
            var expected = "{ \"out\" : { \"merge\" : \"name\", \"db\" : \"database\", \"sharded\" : true } }";

            Assert.AreEqual(expected, options.ToJson());
        }
示例#3
0
        /// <summary>
        /// Returns all the scenarios containing at least one of the specified access points.
        /// </summary>
        /// <param name="accessPoints">The MAC addresses associated to the possible accessPoints.</param>
        /// <returns></returns>
        public IEnumerable <Scenario> GetByPossibleAccessPoints(IEnumerable <AccessPoint> accessPoints)
        {
            if (accessPoints == null)
            {
                throw new ArgumentNullException("accessPoints");
            }
            if (accessPoints.Count() == 0)
            {
                return(new List <Scenario>().AsEnumerable());
            }

            //// Get all ids of scenarios containing at least one access point in the list
            var accessPointsBSON = new BsonArray();

            foreach (var ap in accessPoints)
            {
                accessPointsBSON.Add(ap.ToBsonDocument());
            }

            // Produce a document for each example in the training set
            var unwindTrainingSet = new BsonDocument
            {
                { "$unwind", "$" + Utils <Scenario> .MemberName(s => s.TrainingSet) }
            };

            // Produce a document for each signal in the example
            var unwindScanSignals = new BsonDocument
            {
                {
                    "$unwind",
                    "$" + Utils <Scenario> .MemberName(s => s.TrainingSet) +
                    "." + Utils <TrainingSetExample> .MemberName(e => e.ScanSignals)
                }
            };

            // show access point on top
            var projectAccessPoint = new BsonDocument
            {
                {
                    "$project",
                    new BsonDocument
                    {
                        { Utils <Scenario> .MemberName(s => s.ContextId), 1 },
                        { Utils <Scenario> .MemberName(s => s.CreationTime), 1 },
                        { Utils <Scenario> .MemberName(s => s.TrainingTime), 1 },
                        {
                            Utils <Scenario> .MemberName(s => s.UpdateTime),
                            "$" + Utils <Scenario> .MemberName(s => s.TrainingSet) +
                            "." + Utils <TrainingSetExample> .MemberName(e => e.ScanDateTime)
                        },
                        { Utils <Scenario> .MemberName(s => s.Features), 1 },
                        { Utils <Scenario> .MemberName(s => s.TruePositives), 1 },
                        { Utils <Scenario> .MemberName(s => s.FalsePositives), 1 },
                        {
                            Utils <ScanSignal> .MemberName(s => s.AP),
                            "$" + Utils <Scenario> .MemberName(s => s.TrainingSet) +
                            "." + Utils <TrainingSetExample> .MemberName(e => e.ScanSignals) +
                            "." + Utils <ScanSignal> .MemberName(s => s.AP)
                        }
                    }
                }
            };

            // Filter out document using access point list
            var matchAccessPoints = new BsonDocument
            {
                {
                    "$match",
                    new BsonDocument
                    {
                        {
                            Utils <ScanSignal> .MemberName(s => s.AP),
                            new BsonDocument
                            {
                                { "$in", accessPointsBSON }
                            }
                        }
                    }
                }
            };

            // access point no more needed, group using all other fields
            var group = new BsonDocument
            {
                {
                    "$group",
                    new BsonDocument
                    {
                        { "_id", "$_id" },
                        {
                            Utils <Scenario> .MemberName(s => s.ContextId),
                            new BsonDocument
                            {
                                { "$first", "$" + Utils <Scenario> .MemberName(s => s.ContextId) }
                            }
                        },
                        {
                            Utils <Scenario> .MemberName(s => s.CreationTime),
                            new BsonDocument
                            {
                                { "$first", "$" + Utils <Scenario> .MemberName(s => s.CreationTime) }
                            }
                        },
                        {
                            Utils <Scenario> .MemberName(s => s.TrainingTime),
                            new BsonDocument
                            {
                                { "$first", "$" + Utils <Scenario> .MemberName(s => s.TrainingTime) }
                            }
                        },
                        {
                            Utils <Scenario> .MemberName(s => s.UpdateTime),
                            new BsonDocument
                            {
                                { "$max", "$" + Utils <Scenario> .MemberName(s => s.UpdateTime) }
                            }
                        },
                        {
                            Utils <Scenario> .MemberName(s => s.Features),
                            new BsonDocument
                            {
                                { "$first", "$" + Utils <Scenario> .MemberName(s => s.Features) }
                            }
                        },
                        {
                            Utils <Scenario> .MemberName(s => s.TruePositives),
                            new BsonDocument
                            {
                                { "$first", "$" + Utils <Scenario> .MemberName(s => s.TruePositives) }
                            }
                        },
                        {
                            Utils <Scenario> .MemberName(s => s.FalsePositives),
                            new BsonDocument
                            {
                                { "$first", "$" + Utils <Scenario> .MemberName(s => s.FalsePositives) }
                            }
                        }
                    }
                }
            };


            // prepare aggregation pipeline
            var pipeline = new[]
            {
                unwindTrainingSet,
                unwindScanSignals,
                projectAccessPoint,
                matchAccessPoints,
                group
            };

            List <Scenario> scenarios;

            try
            {
                var result = this.MongoConnectionHandler.MongoCollection.Aggregate(pipeline);
                scenarios = result.ResultDocuments
                            .Select(BsonSerializer.Deserialize <Scenario>)
                            .ToList();
            }
            catch (MongoException ex)
            {
                throw new DatabaseException(Properties.Resources.MsgErrorScenarioRead, ex);
            }

            if (scenarios.Count == 0)
            {
                // no suitable scenarios found
                return(scenarios.AsEnumerable());
            }



            // prepare for map reduce
            string ts = Utils <Scenario> .MemberName(s => s.TrainingSet);

            string signals = Utils <TrainingSetExample> .MemberName(e => e.ScanSignals);

            string signalAP = Utils <ScanSignal> .MemberName(s => s.AP);

            string featureAP = Utils <FeatureKey> .MemberName(f => f.AP);

            string signalValue = Utils <ScanSignal> .MemberName(s => s.RSSI);

            string scenarioId = Utils <FeatureKey> .MemberName(f => f.ScenarioId);

            string map = @"
                function map() 
                {
	                var ts_length = this."     + ts + @".length;
	                var scenario_id = this._id;
	                this."     + ts + @".forEach(function(ts) 
                    {
		                ts."         + signals + @".forEach(function(signal) 
                        {
			                emit(
                            {
                                " + scenarioId + @": scenario_id,
                                " + featureAP + @": signal." + signalAP + @"
                            },
			                {	
				                sum: signal."                 + signalValue + @",
				                min: signal."                 + signalValue + @",
				                max: signal."                 + signalValue + @",
				                count: 1,
				                diff: 0,
				                count_max : ts_length
                            });
		                });
	                });
                }";

            string reduce = @"
                function reduce(key, values) 
                {
                    var a = values[0]; // will reduce into here
                    for (var i=1/*!*/; i < values.length; i++)
                    {
                        var b = values[i]; // will merge 'b' into 'a'

                        // temp helpers
                        var delta = a.sum/a.count - b.sum/b.count; // a.mean - b.mean
                        var weight = (a.count * b.count)/(a.count + b.count);
        
                        // do the reducing
                        a.diff += b.diff + delta*delta*weight;
                        a.sum += b.sum;
                        a.count += b.count;
                        a.min = Math.min(a.min, b.min);
                        a.max = Math.max(a.max, b.max);
                    }
                    return a;
                }";

            string avg = Utils <FeatureValue> .MemberName(f => f.Avg);

            string variance = Utils <FeatureValue> .MemberName(f => f.Variance);

            string min = Utils <FeatureValue> .MemberName(f => f.Min);

            string max = Utils <FeatureValue> .MemberName(f => f.Max);

            string reliability = Utils <FeatureValue> .MemberName(f => f.Reliability);

            string finalize = @"
                function finalize(key, value) 
                { 
	                var res = new Object();
                    res." + avg + @" = value.sum / value.count;
                    res." + variance + @" = value.diff / value.count;
                    res." + reliability + @" = value.count / value.count_max;
	                res."     + min + @" = value.min;
	                res."     + max + @" = value.max;
                    return res;
                }";

            var options = MapReduceOptions
                          .SetOutput(MapReduceOutput.Merge(Utils <Feature> .CollectionName))
                          .SetFinalize(new BsonJavaScript(finalize));


            var featureService = new FeatureService();

            foreach (var scenario in scenarios)
            {
                if (scenario.UpdateTime > scenario.TrainingTime)
                {
                    // perform training
                    var query = Query <Scenario> .EQ(s => s.Id, scenario.Id);

                    try
                    {
                        var result = this.MongoConnectionHandler.MongoCollection
                                     .MapReduce(query, map, reduce, options);
                        scenario.Features = result.GetResults().Select(BsonSerializer.Deserialize <Feature>).ToList();
                        var update = Update <Scenario> .Set(s => s.TrainingTime, DateTime.Now);

                        this.MongoConnectionHandler.MongoCollection.FindAndModify(query, SortBy.Null, update);
                    }
                    catch (MongoException ex)
                    {
                        throw new DatabaseException(Properties.Resources.MsgErrorScenarioTrain + scenario.Id, ex);
                    }
                }
                else
                {
                    // training not needed
                    scenario.Features = featureService.GetByScenario(scenario.Id.ToString()).ToList();
                }
            }

            return(scenarios.AsEnumerable());
        }