Как реализовать функцию $filter MongoDB в Matlab с использованием java-драйвера mongoDB

Я только начал изучать mongoDB, и вот моя проблема: в моей базе данных Mongo у меня есть коллекция с такими элементами, как:

{
    "Common Name": "Tom",
    "Country": "Germany",
    "apperiance":   [{
                        "colour": "white",
                        "hair": "long",
                        "height": 180,
                        "weight": [100, 90],
                        "weights":  {
                                        "weights1": 99999,
                                        "weights2": 100, 
                                        "weights3": 99999, 
                                        "weights4": 99999, 
                                        "weights5": 99999, 
                                        "weights6": 90
                                                    }
                     },
                    {
                       "colour": "white",
                       "hair": "short",
                       "height": 170,
                       "weight": [95, 90],
                       "weights":   {
                                        "weights1": 99999,
                                        "weights2": 95, 
                                        "weights3": 99999, 
                                        "weights4": 99999, 
                                        "weights5": 99999, 
                                        "weights6": 90
                                    }
                     }]
    }

Если я напишу следующий код в mongoDB:

db.collection1.aggregate([
   {
        $match: {
                    $and:[
                            {"apperiance.weight": 100},
                            {"apperiance.height":180},
                            {"apperiance.hair":"long"}
                        ]
                }
    },
   {
        $project: {
         "apperiance": {
            $filter: {
               input: "$apperiance",
               as: "apperiances",
               cond: { $and:[{$eq: [ "$$apperiances.height", 180 ]},{$eq: [ "$$apperiances.hair", "long" ]}] }
            }
         }
       }
     },
     {
        $project: {"apperiance.weights":1, "_id":0}                     
     }
]).pretty()

Я получаю желаемый результат:

{
        "apperiance" : [
                {
                        "weights" : {
                                "weights1" : 99999,
                                "weights2" : 100,
                                "weights3" : 99999,
                                "weights4" : 99999,
                                "weights5" : 99999,
                                "weights6" : 90
                        }
                }
        ]
}

Я хотел бы добиться того же в Matlab через java-драйвер mongoDB. Сейчас у меня есть текущий код в Matlab:

%% call java driver
javaaddpath('mongo-java-driver-3.4.2.jar');

import com.mongodb.*;

%% connect to Mongo client
m   = MongoClient('localhost', 27017);
% handle to database              
db  = m.getDB('test');                                   
% handle to collection 
col = db.getCollection('collection1') ;                 

%% match
%first match
mtch_pogoj1 = BasicDBObject('apperiance.height', ...              
    BasicDBObject('$eq',180)) ;                     

%second match
mtch_pogoj2 = BasicDBObject('apperiance.weight', ...        
    BasicDBObject('$eq',100)) ;                     

%collect both matches in new variable pogoj
pogoj = BasicDBList(); 
pogoj.add(mtch_pogoj1);
pogoj.add(mtch_pogoj2);
%both matches need to be considered with $and statement
mtch_cel = BasicDBObject('$and', pogoj);
% pipe-line command match, full query
mtch1  = BasicDBObject('$match',  mtch_cel) ;             

%% projection
% start specifying projection
prj1a = BasicDBObject() ; 
% do not keep id                             
prj1a.put('_id',0) ; 
% keep 'weights'                                   
prj1a.put('apperiance.weights',1) ;                           

% pipe-line command project
prj1  = BasicDBObject('$project',  prj1a) ;

%% define pipeline
% start specifying pipeline list 
aggr_list = BasicDBList();                                                      
aggr_list.add(mtch1);                                   % add first match 
aggr_list.add(prj1);                                    % add projection

%% do the actual aggregation according pipeline
% create aggregation output
ao  = col.aggregate(aggr_list); 
% cursor to results of the aggregation                        
cur = ao.results().iterator();                          
fprintf('show aggregation results\n')
mm_cursor_showcontents( cur ) ;

К сожалению, код Matlab выводит все веса:

 show aggregation results
{ "apperiance" : [ { "weights" : { "weights1" : 99999.0 , "weights2" : 100.0 , "weights3" : 99999.0 , "weights4" : 99999.0 , "weights5" : 99999.0 , "weights6" : 90.0}} , { "weights" : { "weights1" : 99999.0 , "weights2" : 95.0 , "weights3" : 99999.0 , "weights4" : 99999.0 , "weights5" : 99999.0 , "weights6" : 90.0}}]}

Я хотел бы вывести только желаемые веса в поддокументе, где «высота»: 180 и «вес»: [100, 90]. Я знаю, что мне нужно реализовать функцию $filter, но я просто не могу понять, как это сделать с помощью java-драйвера mongo.

РЕДАКТИРОВАТЬ: я реализовал функцию $filter, как это было предложено в связанном ответе.

%%filter function
filterExpression = BasicDBObject() ;                               
filterExpression.put('input', '$apperiance');
filterExpression.put('as', 'apperiances');
equal=(BasicDBObject('$$apperiances.height', 180));
filterExpression.put('cond', BasicDBObject('$eq',equal));
filter= BasicDBObject('$filter', filterExpression);

project1 = BasicDBObject() ;
project1.put('apperiance',filter);
project_full  = BasicDBObject('$project',  project1)

Вывод project_full теперь такой же, как тот, который я пишу в оболочке mongodb db. Но если я добавлю приведенный выше код в aggr_list.add(project_full) и попытаюсь выполнить полный код в Matlab, я получу следующую ошибку.

Произошло исключение Java: com.mongodb.MongoCommandException: команда завершилась ошибкой 168: «Нераспознанное выражение $$apperiances.height» на сервере localhost:27017. Полный ответ: { "ok" : 0.0, "errmsg": "Нераспознанное выражение '$$apperiances.height'", "code" : 168, "codeName": "InvalidPipelineOperator" }

Я также пытался реализовать такой код

filterExpression.put('cond', BasicDBObject('$eq',Arrays.<Object> asList('$$apperiances.height', 180)));

но оператор Массивы. asList не распознается Matlab. Я застрял и не знаю, как реализовать это в Matlab, чтобы заставить его работать.

Если кто-то может помочь мне найти решение или обходной путь к моей проблеме, я был бы очень признателен.


person pg1    schedule 25.06.2017    source источник
comment
Что выяснить? Это всего лишь конструкции DBObject и List для {} и [] соответственно при преобразовании объектов JavaScript в любом случае. Вы уже сделали большую часть этого. Связан с ответом, показывающим конструкцию BasicDBObject $filter   -  person Neil Lunn    schedule 26.06.2017
comment
@NeilLunn благодарю вас за то, что вы указали мне правильное направление. Я отредактировал свой вопрос, добавив новый код, который у меня есть сейчас в отношении функции $filter. Проблема, которая у меня есть сейчас, заключается в реализации части массивов. asList в матлабе. Я считаю, что это последняя часть, которая заставит мой код работать. Если вы снова сможете указать мне правильное направление и помочь мне, я был бы очень признателен.   -  person pg1    schedule 16.07.2017
comment
Если у вас есть новый вопрос, задайте новый вопрос. По прошествии месяца, когда вам указали на дублирующий ответ, потому что вы не знали правильный процесс, нет такой вещи, как редактирование вашего вопроса. Есть только новый вопрос. Но, пожалуйста, прочитайте материал и правильно отладьте его, прежде чем спрашивать.   -  person Neil Lunn    schedule 17.07.2017