MongoDB - request with operations with array parameter elements

Im new to MongoDB and Im trying to figure out if I can execute this query conveniently and with decent performance using MongoDB. Id like to pass the numeric and array parameters into the query and use them to perform operations on the elements by the array values ​​in each document in the collection. Is it possible?

eg. The collection contains the following documents:

{ "name" : "item1", "m" : 5.2, "v" : 1.1, "data1" : [ 0, 0, 0.3, 0.7, 0.95, 0.9, 0.75, 0.4, 0.1, 0 ], "data2" : [ 0, -1, 0, 1, 1, 0 ] } 

And I have another β€œsearch” document that might look something like this:

 { "x" : 8, "K" : 1, "dataA" : [ 0, 0, 0, 0, 0, 0, 0, 0.5, 1, 0.5], "dataB" : [ 0, -2, 0, 1, 1, 0 ] } 

I want to fulfill a query or reduce a map using the above search document versus the collection above, which returns a collection containing:

 { "name", "y" = fn(m, v, x, K) = Kvx^(1/m) (not the real formula but just an example) "dataF" = Max(i=0..9) {data1[i] * dataA[i] } "dataS" = Sum(j=0..5) {data2[j] * dataB[j] } } where y>0 

So for the above example, the return result would be

 { "name" : "item1", "y" : 1 * 1.1 * 8^5.2 = 1.641 "dataF" : Max(..., 0.4*0.5, 0.1*1, 0 * 0.5 ) = 0.2 "dataS" : 0*0 + (-1)*(-2) + 0*0 + 1*1 + 1*1 + 0*0 = 4 } 

Will it be possible / convenient with MongoDB?

Note. My application will have more standard criteria included in the search using standard MongoDB operations, so I was hoping to include the above processing in the request and not do it on the client.

+4
source share
1 answer

Here's the map / version to reduce:

 db.data.save({ "name" : "item1", "m" : 5.2, "v" : 1.1, "data1" : [ 0, 0, 0.3, 0.7, 0.95, 0.9, 0.75, 0.4, 0.1, 0 ], "data2" : [ 0, -1, 0, 1, 1, 0 ] }); db.data.mapReduce( function() { var searchdoc = { "x" : 8, "K" : 1, "dataA" : [ 0, 0, 0, 0, 0, 0, 0, 0.5, 1, 0.5], "dataB" : [ 0, -2, 0, 1, 1, 0 ] }; var result = {name: this.name}; result.y = searchdoc.K * this.v * Math.pow(searchdoc.x, 1 / this.m); if(result.y > 0) { result.dataF = 0; for(i=0;i<this.data1.length;i++) { var f = this.data1[i] * searchdoc.dataA[i]; if(f > result.dataF) { result.dataF = f; } } result.dataS = 0; for(i=0;i<this.data2.length;i++) { var s = this.data2[i] * searchdoc.dataB[i]; result.dataS += s; } emit(this.name, result); } }, function(key, values){}, {out: {inline: 1}}); 

result:

 { "results" : [ { "_id" : "item1", "value" : { "name" : "item1", "y" : 1.640830939540542, "dataF" : 0.2, "dataS" : 4 } } ], "timeMillis" : 0, "counts" : { "input" : 1, "emit" : 1, "reduce" : 0, "output" : 1 }, "ok" : 1, } 

This is the shell version:

 db.data.save({ "name" : "item1", "m" : 5.2, "v" : 1.1, "data1" : [ 0, 0, 0.3, 0.7, 0.95, 0.9, 0.75, 0.4, 0.1, 0 ], "data2" : [ 0, -1, 0, 1, 1, 0 ] }); var searchdoc = { "x" : 8, "K" : 1, "dataA" : [ 0, 0, 0, 0, 0, 0, 0, 0.5, 1, 0.5], "dataB" : [ 0, -2, 0, 1, 1, 0 ] }; var search = function(searchdoc) { db.data.find().forEach(function(obj) { var result = {name:obj.name}; result.y = searchdoc.K * obj.v * Math.pow(searchdoc.x, 1 / obj.m); if( result.y > 0 ) { result.dataF = 0; for(i=0;i<obj.data1.length;i++) { var f = obj.data1[i] * searchdoc.dataA[i]; if(f > result.dataF) { result.dataF = f; } } result.dataS = 0; for(i=0;i<obj.data2.length;i++) { var s = obj.data2[i] * searchdoc.dataB[i]; result.dataS += s; } db.results.save(result); } }); } search(searchdoc); db.results.find(); { "_id" : ObjectId("4f08ffe4264d23670eeaaadf"), "name" : "item1", "y" : 1.640830939540542, "dataF" : 0.2, "dataS" : 4 } 
+2
source

Source: https://habr.com/ru/post/1389852/


All Articles