Node.js orm2 - проблема с поиском новых ассоциаций в отношениях OneToMany
Я играю с node-orm2, чтобы понять, каково это использовать в RESTful API. Я использую базу данных Postgres на сервере.
Я пытаюсь изменить их документы, где у меня есть отношение OneToMany между человеком и задачей со следующим в одном файле:
app.js
'strict'
// Based on http://blog.modulus.io/nodejs-and-express-create-rest-api
// but with my own twists!
var express = require('express');
var app = express();
var orm = require('orm');
// Helpers
var collectionize = function(target){
if(typeof target == 'Object'){
return [target];
}
return target;
};
// Configure the app with any middleware
app.use(express.bodyParser());
app.use(orm.express("postgres://rodrigomartell:password@localhost/postgres",{
define : function(db, models, next){
// Define models
models.Person = db.define("Person",
{
name : String,
surname : String,
age : Number,
male : Boolean,
continent: ["enum1", "enum2"],
data : Object
},
{
methods : {
fullName: function(){
return this.name + this.surname;
}
},
validations : {
name: orm.enforce.unique("name already taken!"),
age : orm.enforce.ranges.number(18, undefined, "under-age")
},
autoFetch : true // global eager load
}
);
models.Task = db.define("Task",
{
description: String
}
);
// Relations
models.Task.hasOne('person', models.Person, {reverse:'tasks', required: true});
// Finally drop and sync this puppy
db.drop(function(){
db.sync(function(){
console.log('All good');
// Create one Person on load
db.models.Person.create([{
name : "Kenny",
surname : "Powers",
age : 34,
male : true,
continent: "enum1"
}], function(err, items){
var person = items[0];
db.models.Task.create([{description:'Heyo!', person_id: person.id}], function(err, tasks){
console.log(err,tasks);
});
});
// Press on?
next(); // After synching, get on with the rest of the app?
},function(err){
console.log('No good', err);
});
});
}
}));
// Configure the routes and that
app.get("/people", function(req,res){
console.log('requested');
res.type('text/plain');
// req.models is a reference to models in the middleware config step
req.models.Person.find(null, function(err, people){ // There must be a neater way to findAll?
res.json(people);
});
});
app.post("/people", function(req,res){
console.log('requested');
res.type('text/plain');
req.models.Person.create(collectionize(req.body), function(err, newPerson){
if(err){
res.json({error: err});
}
else{
res.json(newPerson);
}
});
});
app.get("/tasks", function(req, res){
res.type('text/plain');
req.models.Task.find(null, function(err, tasks){ // There must be a neater way to findAll?
res.json(tasks);
});
});
app.post("/tasks", function(req, res){
res.type('text/plain');
var task = req.body;
req.models.Task.create([req.body], function(err, task){
if(err){
res.json(err);
}
else{
res.json(task);
}
});
});
// Listen up!
app.listen(4730, function(){
console.log('Listening on http://localhost:4730');
});
Я установил GET и POST маршруты для следующих ресурсов:
{ПОЛУЧИТЬ, ПОСТ} / люди
{GET,POST} / задачи
При начальной загрузке БД я создаю экземпляр Person с задачей просто иметь что-то в БД.
Я могу сделать GET на localhost:4730/people и вернуть человека, созданного во время загрузки, с его задачей (потрясающе):
[{
name : "Kenny",
surname : "Powers",
age : 34,
male : true,
continent: "enum1",
data : null,
id : 1,
tasks : [
{
description: "Heyo!",
id: 1,
person_id: 1
}
]
}]
Если я сделаю GET на localhost:4730/tasks, я вернусь, как и ожидалось:
[
{
description: "Heyo!",
id: 1,
person_id: 1
}
]
Теперь вот начало моей проблемы:
Если я делаю POST для localhost:4730/tasks с полезной нагрузкой:
{
description: "Another task",
person_id: 1
}
И затем сделать свежий GET на localhost:4730/tasks, я получаю это, как и ожидалось:
[{
description: "Heyo!",
id: 1,
person_id: 1
},
{
description: "Another task",
id: 2,
person_id: 1
}]
Теперь, выполняя новый GET для localhost: 4730 / чел., Можно было бы ожидать, чтобы показать две задачи, назначенные для person_id 1 (Кенни Пауэрс), но, увы, ассоциация, похоже, зарегистрирована на многих сторонах, но не на одной стороне отношений:
[{
name : "Kenny",
surname : "Powers",
age : 34,
male : true,
continent: "enum1",
data : null,
id : 1,
tasks : [
{
description: "Heyo!",
id: 1,
person_id: 1
}
]
}]
Я не могу работать из документов, где я могу пойти не так. Кто-нибудь сталкивался с подобными проблемами?
Благодарю.
2 ответа
Я только проверял этот несвежий вопрос и увидел, что получил за это значок. Не уверен, хорошо это или плохо (погуглю через минуту), но я восприму это как хорошее.
Во всяком случае, я просто поиграл с этим еще немного и нашел этот пост, который заставил меня попробовать отключить кеш (true по умолчанию) в модели Person.
Таким образом, все работает, если в модели Person добавляется новое свойство после autoFetch, чтобы установить для кэша значение false. Это должно выглядеть так:
models.Person = db.define("Person",
{
name : String,
surname : String,
age : Number,
male : Boolean,
continent: ["enum1", "enum2"],
data : Object
},
{
methods : {
fullName: function(){
return this.name + this.surname;
}
},
validations : {
name: orm.enforce.unique("name already taken!"),
age : orm.enforce.ranges.number(18, undefined, "under-age")
},
autoFetch : true, // global eager load
cache : false // Important as otherwise it doesn't update the relationship, why?
}
);
Я не могу сказать, что полностью понимаю, почему это работает, и буду стараться изо всех сил, но рад, что это исправлено.
Я надеюсь, что это поможет любому приземлиться здесь с подобной проблемой. Я собираюсь показать мой новый значок ватной палочки моим воображаемым друзьям в пустой пустынной сцене...
Удивительный вопрос, я тоже ничего не мог найти по этому поводу. Решив, что не нужно отключать кэширование, а вместо этого очистить его, пройдя через git-репозиторий, я обнаружил следующее:
orm.singleton.clear(instance._singleton_uid);
Это работает, но довольно грязно. Может помочь кому-то, хотя.
Обновить:
Вы можете установить instance.cacheSaveCheck
к истине, и это также исправит это!