Допустим, у меня есть две коллекции с именами CollectionA и CollectionB. Обе коллекции имеют разные поля. CollectionA будет иметь несколько документов с одним и тем же полем, CollectionB содержит только один документ
Пример
CollectionA
{
"UniqeId" :1,
"Hobbies" : "Eating"
},
{
"UniqeId" :2,
"Hobbies" : "Sleeping"
},
{
"UniqeId" :3,
"Hobbies" : "Walking"
}
CollectionB
{
"UserName" :"Sukuna",
"UserType" : "Villan"
}
Я хочу, чтобы вывод был таким
{
"UniqeId" :1,
"Hobbies" : "Eating",
"UserName" :"Sukuna",
"UserType" : "Villan"
}
Учтите, что все документы в CollectionA будут содержать одинаковые поля. И вы можете видеть, что между двумя коллекциями нет уникальных полей, и вы можете видеть, что нам нужно применить фильтр в CollectionA. т.е.) UniqeId=1
Я использую С#, и я могу сделать два запроса БД, чтобы получить эти сведения о коллекции (один запрос для вывода CollectionA и другой для вывода CollectionB), и мне удается объединить оба на уровне API, чтобы получить желаемый результат, но я хочу сделать на самом уровне БД,
Мне не нужны два вызова БД, которые снижают производительность API, так можно ли в любом случае добиться этого за один вызов БД или с помощью любого агрегатного конвейера? Заранее спасибо
@ProgrammingLlama Нет, я просто хочу, чтобы все поля в обеих коллекциях были в одном документе, этот единственный документ будет содержать все поля из обеих коллекций. Допустим, в CollectionA есть 2 поля, а в CollectionB — 2 поля. Выходная коллекция будет содержат 4 поля. Надеюсь, это прояснится, и я также добавил точный пример
Итак, если у вас есть 2 документа в каждой коллекции, вы просто хотите объединить все поля из всех документов в обеих коллекциях в один документ?
Обратите внимание, что коллекция содержит документы, и не все документы должны содержать одни и те же поля, даже в одной коллекции. Также обратите внимание, что результаты, которые вы получаете от запроса, являются документами — вы не создаете новую коллекцию.
@ProgrammingLlama, да, я изменил заголовок с коллекции на документ, и вы правы, мне нужно объединить документы из двух разных коллекций. Вы можете предположить, что все документы в коллекции будут иметь одинаковые поля, и я обновлю пример для большего количества ясность, так есть ли способ добиться этого?
Итак, вы ожидаете 3 таких результата, как это? Или, по крайней мере, это то, что в конечном итоге будет получено для запроса Id = 1, затем Id = 2, затем Id = 3?
[{"UniqueId":1,"Hobbies":"Eating","UserName":"Sukuna","UserType":"Villain"},{"UniqueId":2,"Hobbies":"Sleeping","UserName":"Sukuna","UserType":"Villain"},{"UniqueId":3,"Hobbies":"Walking","UserName":"Sukuna","UserType":"Villain"}] (при условии, что вы запросили каждый из них, а затем поместили его в список). Это правильно?
@ProgrammingLlama В коллекции A я применю фильтр, чтобы получить один документ, а в CollectionB будет только один документ, мне нужно объединить результат документа CollectionB с отфильтрованным документом CollectionA
Так это "да", верно? ХОРОШО.
@ProgrammingLlama, да, приведенный выше вариант тоже подходит, по крайней мере, мы получим один запрос, я применю к нему фильтр. Если вы знаете ответ, напишите, это поможет. Спасибо
Извините, у меня сейчас нет времени, но вам, вероятно, понадобится $lookup с конвейером, чтобы это сделать.
Да, я уже прошел через это, и меня беспокоит только то, что у этих двух коллекций нет общего поля, иначе с помощью поиска мы можем добиться этого.
С одной стороны, вы говорите, что вам не нужны два запроса, но тогда вы, похоже, не хотите (IMO хакерский) способ добиться этого без двух запросов.
Привет, позвольте мне прояснить здесь, я не хочу два вызова БД, я хочу требуемый результат в одном вызове БД, поэтому, если для этого есть один запрос, это очень ценится, и я считаю, что нам нужно общее поле в двух коллекции для выполнения поиска. К сожалению, в этом случае нет общего поля
Я почти уверен, что вы можете сделать это с конвейером, не требуя поля для сопоставления.
Да, я могу сделать это с помощью unionWidth и group, и ЮТинг в любом случае опубликовал ответ с поиском. Спасибо.





поиск с помощью localField 1 и ForeignField 1
db.a.aggregate([
{
$lookup: {
from: "b",
localField: "1",
foreignField: "1",
as: "docs"
}
},
{
$replaceRoot: {
newRoot: {
$mergeObjects: [
"$$ROOT",
{ $first: "$docs" }
]
}
}
},
{
$unset: [ "docs", "_id" ]
},
{
$group: {
_id: "$UserName",
doc: { $first: "$$ROOT" }
}
},
{
$replaceWith: "$doc"
}
])
Спасибо, я могу сделать это с помощью unionWith и группы, и я также опубликовал решение здесь, однако я отмечу это как принятое решение. Если вы знаете какие-либо преимущества использования поиска по сравнению с unionWith и группой (например, в производительности), пожалуйста поделитесь своими мыслями. Это будет полезно для других.
Наконец, после множества проб и ошибок и игры с конвейером, я могу сделать это в совокупном конвейере, и я использую unionWith и группу. Вот код С#
var pipeline1= new BsonDocument("$unionWith",
new BsonDocument
{
{ "coll", "CollectionB" },
{ "pipeline",
new BsonArray
{
new BsonDocument("$match",
new BsonDocument("UniqeId", 1))
} }
});
var pipeline2 = new BsonDocument("$group",
new BsonDocument
{
{ "_id", 0 },
{ "merged",
new BsonDocument("$push", "$$ROOT") }
});
var pipeline3 = new BsonDocument("$replaceRoot",
new BsonDocument("newRoot",
new BsonDocument("$mergeObjects", "$merged")));
var pipeline4 = new BsonDocument("$project",
new BsonDocument("_id", 0));
BsonDocument[] pipeline = new BsonDocument[] { pipeline1, pipeline2, pipeline3, pipeline4 };
var dbResponse = await collection.Aggregate<BsonDocument>(pipeline).ToListAsync();
Итак, если бы у вас было две записи в CollectionA, то вы бы ожидали 2 результата, оба с Sukuna/Villain? И если бы у вас было два целых в CollectionA и CollectionB, вы бы ожидали 4 результата (комбинация первых элементов, первого и второго, второго и первого, а затем второго и второго из двух коллекций соответственно)?