Почему моя агрегация Mon go не работает должным образом на вложенном документе? - PullRequest
0 голосов
/ 29 апреля 2020

У меня есть следующие классы:

@Document(collection = "rCollection")
public class R{
    public R() {
    }
    @Id
    private String id;

    @TextIndexed(weight=2)
    private String fp;

    @TextIndexed(weight=1)
    private String sp;

    @DBRef
    @Indexed
    private P p;

    @DBRef
    private User user;
    private String date;
}

И:

@Document(collection = "pCollection")
public class P {

    public P() {}

    @Id 
    private String id;
}

Я хотел бы найти в RCollection и group результаты, основанные на p элемент класса. Поскольку id в классе P уникален, я пытаюсь сгруппировать результаты на основе p.id. У меня есть следующий код в моем хранилище:

TextCriteria criteria = TextCriteria.forDefaultLanguage().matchingAny(text);
MatchOperation match = Aggregation.match(criteria);
GroupOperation group = Aggregation.group("p.id");
Aggregation aggregation = Aggregation.newAggregation(match, group);

AggregationResults<finalResults> results = mongoTemplate.aggregate(aggregation, "rCollection", finalResults.class);

List<finalResults> result= results.getMappedResults();

System.out.println("size is: "+result.size());
System.out.println("output = "+result.get(0).toString());

Код работает нормально, когда я использую fp вместо p.id в приведенном выше коде. Но если я использую p.id, я вижу, что результат равен нулю. result.size() равно 1, но result.get(0).toString() равно нулю. То есть следующий вывод:

size is: 1
output = FinalResults [fp=null, sp=null]

Вот мой класс finalResults (на самом деле он точно такой же, как класс R):

private class FinalResults{

    public finalResults() {
    }
    private String id;

    private String fp;
    private String sp;

    private P p;
    private User user;
    private String date;

    @Override
    public String toString() {
        return "FinalResults [fp=" + fp + ", sp=" + sp +"]";
    }
}

ОБНОВЛЕНИЕ : Пример данных: все, что у меня есть в rCollection:

{ 
"_id" : ObjectId("5e9db54c3b4b97129065b773"),
 "_class" : "com.main.tothepoint.model.R", 
"fp" : "hello\ni\nam\n",
"sp " : "hi",
"date" : "Mon Apr 20 16:44:28 CEST 2020",
"p" : DBRef("p", ObjectId("5e9db54c3b4b97129065b772")),
"user" : DBRef("user", ObjectId("5e5aa321383ba54434092e8d"))
}
{
 "_id" : ObjectId("5e9db7903b4b97129065b775"),
"_class" : "com.main.tothepoint.model.R", 
"fp " : "hi",
"sp " : "hello",
"date" : "Mon Apr 20 16:54:08 CEST 2020",
"p" : DBRef("p", ObjectId("5e9db7903b4b97129065b774")),
"user" : DBRef("user", ObjectId("5e6e567dc77ed32ab4ad796b"))
}
{
"_id" : ObjectId("5e9db7a73b4b97129065b777"),
"_class" : "com.main.tothepoint.model.R",
"fp" : "hi",
"sp" : "",
"date" : "Mon Apr 20 16:54:31 CEST 2020",
"p" : DBRef("p", ObjectId("5e9db7a73b4b97129065b776")),
"user" : DBRef("user", ObjectId("5e6e567dc77ed32ab4ad796b"))
}
{
"_id" : ObjectId("5e9ef7e04b6e5d338c02fda0"),
"_class" : "com.main.tothepoint.model.R",
"fp" : "hello",
"sp" : "",
"date" : "Tue Apr 21 15:40:48 CEST 2020",
"p" : DBRef("p", ObjectId("5e9ef7e04b6e5d338c02fd9f")),
"user" : DBRef("user", ObjectId("5e5aa321383ba54434092e8d"))
}
{
"_id" : ObjectId("5e9ef82b4b6e5d338c02fda3"),
"_class" : "com.main.tothepoint.model.R",
"fp " : "hello",
"sp" : "",
"date" : "Tue Apr 21 15:42:03 CEST 2020",
"p" : DBRef("p", ObjectId("5e9ef82b4b6e5d338c02fda2")),
"user" : DBRef("user", ObjectId("5e9ef81f4b6e5d338c02fda1"))
}

И соответствующая часть из pCollection:

{
 "_id" : ObjectId("5e9db54c3b4b97129065b772"),
"_class" : "com.main.tothepoint.model.P",
"p_name" : "Hisar",
"longitude" : 75.7216527,
"latitude" : 29.1491875
}


{
"_id" : ObjectId("5e9db7a73b4b97129065b776"),
"_class" : "com.main.tothepoint.model.P",
"p_name" : "Helsinki",
"longitude" : 24.9383791,
"latitude" : 60.16985569999999
}

В данных есть еще несколько элементов, чем первая часть моего вопроса, потому что я пытался сделать свои образцы классов как можно меньше. В моем коде я хотел бы искать тексты, которые могут существовать в fp и sp, например, я ищу "привет", а затем я вижу размер моего результата, равный 2187.

1 Ответ

0 голосов
/ 29 апреля 2020

Проблема здесь:

GroupOperation group = Aggregation.group("p.id");

В оболочке MongoDB это будет выглядеть так:

{$group:{ _id:"$p._id" }}

Как видите, групповой этап не завершен. Вам нужно накапливать поля fp и sp на групповом этапе. Чтобы собрать все возможные значения для полей fp и sp, нам нужно использовать операторы $push (массив с дублирующимися значениями) или $addToSet (набор с уникальными значениями) и добавить дополнительные $unwind. этапы.

TextCriteria criteria = TextCriteria.forDefaultLanguage().matchingAny(text);
MatchOperation match = Aggregation.match(criteria);
GroupOperation group = Aggregation.group("p.id").push("fp").as("fp").push("sp").as("sp");
UnwindOperation unwindFp = Aggregation.unwind("fp");
UnwindOperation unwindSp = Aggregation.unwind("sp");
Aggregation aggregation = Aggregation.newAggregation(match, group, unwindFp, unwindSp);

AggregationResults<finalResults> results = mongoTemplate.aggregate(aggregation, mongoTemplate.getCollectionName(R.class), FinalResults.class);
...