TL; DR: Попробуйте использовать Html.Partial
вместо Renderpage
Я получал Object reference not set to an instance of an object
, когда пытался сделать вид в представлении, отправив ему модель, например это:
@{
MyEntity M = new MyEntity();
}
@RenderPage("_MyOtherView.cshtml", M); // error in _MyOtherView, the Model was Null
Отладка показала, что модель была Null внутри MyOtherView. Пока я не сменил его на:
@{
MyEntity M = new MyEntity();
}
@Html.Partial("_MyOtherView.cshtml", M);
И это сработало.
Кроме того, причина, по которой я не имел Html.Partial
для начала, заключалась в том, что Visual Studio иногда выдает ошибки, (f9), если он находится внутри другого построенного цикла foreach
, хотя это не ошибка:
@inherits System.Web.Mvc.WebViewPage
@{
ViewBag.Title = "Entity Index";
List<MyEntity> MyEntities = new List<MyEntity>();
MyEntities.Add(new MyEntity());
MyEntities.Add(new MyEntity());
MyEntities.Add(new MyEntity());
}
<div>
@{
foreach(var M in MyEntities)
{
// Squiggly lines below. Hovering says: cannot convert method group 'partial' to non-delegate type Object, did you intend to envoke the Method?
@Html.Partial("MyOtherView.cshtml");
}
}
</div>
Но я смог запустить приложение без проблем с этим " ошибка". Я смог избавиться от ошибки, изменив структуру цикла foreach
, чтобы выглядеть так:
@foreach(var M in MyEntities){
...
}
Хотя я чувствую, что это потому, что Visual Studio неправильно интерпретировала амперсанды и скобки .
Вы не можете делать то, что хотите, в одном запросе. Вам нужно будет сначала получить список идентификаторов пользователей друга, а затем передать эти идентификаторы во второй запрос, чтобы получить документы и отсортировать их по возрасту.
var user = db.user.findOne({"id" : "001"}, {"friends": 1})
db.user.find( {"id" : {$in : user.friends }}).sort("age" : 1);
Вы можете использовать playOrm, чтобы делать то, что хотите в одном запросе (с S-SQL масштабируемым SQL).
Чтобы иметь все с одним запросом, используя функцию $ lookup в структуре агрегации, попробуйте следующее:
db.User.aggregate(
[
// First step is to extract the "friends" field to work with the values
{
$unwind: "$friends"
},
// Lookup all the linked friends from the User collection
{
$lookup:
{
from: "User",
localField: "friends",
foreignField: "_id",
as: "friendsData"
}
},
// Sort the results by age
{
$sort: { 'friendsData.age': 1 }
},
// Get the results into a single array
{
$unwind: "$friendsData"
},
// Group the friends by user id
{
$group:
{
_id: "$_id",
friends: { $push: "$friends" },
friendsData: { $push: "$friendsData" }
}
}
]
)
Предположим, что содержимое вашей пользовательской коллекции следующее:
{
"_id" : ObjectId("573b09e6322304d5e7c6256e"),
"name" : "John",
"age" : 30,
"friends" : [
"userId1",
"userId2",
"userId3"
]
}
{ "_id" : "userId1", "name" : "Derek", "age" : 34 }
{ "_id" : "userId2", "name" : "Homer", "age" : 44 }
{ "_id" : "userId3", "name" : "Bobby", "age" : 12 }
Результатом запроса будет:
{
"_id" : ObjectId("573b09e6322304d5e7c6256e"),
"friends" : [
"userId3",
"userId1",
"userId2"
],
"friendsData" : [
{
"_id" : "userId3",
"name" : "Bobby",
"age" : 12
},
{
"_id" : "userId1",
"name" : "Derek",
"age" : 34
},
{
"_id" : "userId2",
"name" : "Homer",
"age" : 44
}
]
}
Вы можете сделать это за один раз, используя mongo-join-query
. Вот как это будет выглядеть:
const joinQuery = require("mongo-join-query");
joinQuery(
mongoose.models.User,
{
find: {},
populate: ["friends"],
sort: { age: 1 },
},
(err, res) => (err ? console.log("Error:", err) : console.log("Success:", res.results))
);
В результате ваши пользователи будут упорядочены по возрасту и всем вложенным объектам друзей.
За кулисами mongo-join-query
будет использоваться ваша схема Mongoose, чтобы определить, к каким моделям присоединиться, и создаст конвейер агрегации , который будет выполнять соединение и запрос.
Только заполнить друзей массива.
User.findOne({ _id: "userId"})
.populate('friends')
.exec((err, user) => {
//do something
});
Результат такой же:
{
"_id" : "userId",
"name" : "John",
"age" : 30,
"friends" : [
{ "_id" : "userId1", "name" : "Derek", "age" : 34 }
{ "_id" : "userId2", "name" : "Homer", "age" : 44 }
{ "_id" : "userId3", "name" : "Bobby", "age" : 12 }
]
}
То же самое: Mongoose - использование Populate в массиве ObjectId
MongoDB не имеет объединений, но в вашем случае вы можете сделать:
db.coll.find({friends: userId}).sort({age: -1})
var p = db.sample1.find().limit(2) ,
h = [];
for (var i = 0; i < p.length(); i++)
{
h.push(p[i]['name']);
}
db.sample2.find( { 'doc_name': { $in : h } } );
он работает для меня.
один вид соединения запроса в mongoDB, задает в одной коллекции идентификатор, который соответствует, помещает идентификаторы в список (idlist) и находит использование в другой (или такой же) коллекции с помощью $ in: idlist
u = db.friends.find({"friends": ? }).toArray()
idlist= []
u.forEach(function(myDoc) { idlist.push(myDoc.id ); } )
db.friends.find({"id": {$in : idlist} } )
Похоже, никто не говорил об этом варианте использования Pivot в добавлении к MapReduce. Существует хорошая статья, которая может быть вашим ответом здесь http://cookbook.mongodb.org/patterns/pivot/ Надеюсь, это поможет вам в ваших проектах
https://docs.mongodb.org/manual/reference/operator/aggregation/lookup/
Это документ для запроса соединения в mongodb, это новый функция из версии 3.2.
Так что это будет полезно.