Я только начал изучать 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, чтобы заставить его работать.
Если кто-то может помочь мне найти решение или обходной путь к моей проблеме, я был бы очень признателен.
DBObject
иList
для{}
и[]
соответственно при преобразовании объектов JavaScript в любом случае. Вы уже сделали большую часть этого. Связан с ответом, показывающим конструкциюBasicDBObject
$filter
- person Neil Lunn   schedule 26.06.2017