loopback:如何根据关系的属性加载模型实例

时间:2021-10-03 21:10:00

I have a model Book.

我有一本模特书。

Book can have multiple tags, so there is a hasMany relationship to Tag through BookTags

Book可以有多个标签,因此通过BookTags标记有一个hasMany关系

Now, how do I load all Book instances with tag "history" (for example)? It should be trivial, but I couldn't find out.

现在,如何使用标记“历史记录”(例如)加载所有Book实例?这应该是微不足道的,但我找不到。

In the documentation, there are only examples for values of properties (like strings, booleans etc.) but no examples for loading via relationships. There is the includefilter which loads relationships, but that should apply to loading relationship instances, which is something else (AFAI understand);

在文档中,只有属性值的示例(如字符串,布尔值等),但没有通过关系加载的示例。有一个includefilter加载关系,但这应该适用于加载关系实例,这是其他的东西(AFAI理解);

I tried:

Book.find({
    where: {tags: {name: "history"}}
}, function(err, books) {
}

But that does not work at all. My next bet was trying to load the Tag by id and try to filter by object, but I would not even know how to do it, as there are no "contains" operators in the where clause documentation: https://docs.strongloop.com/display/public/LB/Where+filter#Wherefilter-inq

但这根本不起作用。我的下一个赌注是尝试通过id加载Tag并尝试按对象过滤,但我甚至不知道该怎么做,因为where子句文档中没有“包含”运算符:https://docs.strongloop的.com /显示/公共/ LB /凡+滤波器#Wherefilter-INQ

The ultimate workaround is to:

最终的解决方法是:

  • load the tag via name
  • 通过名称加载标签

  • load all BookTags instances with that tag id, get the book ids
  • 使用该标记id加载所有BookTags实例,获取book id

  • load all Books with those ids
  • 加载所有具有这些ID的书籍

Seems cumbersome and suggests there should be a more elegant solution?

似乎很麻烦,并建议应该有一个更优雅的解决方案?

1 个解决方案

#1


0  

If a book can have many tags, and a tag can have many books, it sounds like you need the hasAndBelongsToMany relationship. This relationship is great for many-to-many's that don't have any additional payload.

如果一本书可以有很多标签,而一个标签可以有很多书,那么听起来你需要hasAndBelongsToMany关系。对于没有任何额外负载的多对多,这种关系非常有用。

common/models/book.json

{
  "name": "Book",
  "base": "PersistedModel",
  "idInjection": true,
  "options": {
    "validateUpsert": true
  },
  "properties": {
    "Title": {
      "type": "string",
      "required": true
    },
    "Author": {
      "type": "string"
    }
  },
  "validations": [],
  "relations": {
    "tags": {
      "type": "hasAndBelongsToMany",
      "model": "Tag",
      "foreignKey": ""
    }
  },
  "acls": [],
  "methods": {}
}

common/models/tag.json

{
  "name": "Tag",
  "base": "PersistedModel",
  "idInjection": true,
  "options": {
    "validateUpsert": true
  },
  "properties": {
    "Name": {
      "type": "string",
      "required": true
    }
  },
  "validations": [],
  "relations": {
    "books": {
      "type": "hasAndBelongsToMany",
      "model": "Book",
      "foreignKey": ""
    }
  },
  "acls": [],
  "methods": {}
}

How to access it? Here is an example boot script that creates some tags and books, and accesses them.

如何访问它?下面是一个示例启动脚本,用于创建一些标记和书籍,并访问它们。

server/boot/seed.js

var async = require('async');
module.exports = function(app) {

    var Tag = app.models.Tag;
    var Book = app.models.Book;

    var tags = [{Name: "Scifi"}, {Name: "Adventure"}];

    Book.create({Title: "Twenty Thousand Leagues Under the Sea", author: "Jules Verne"}, function(err, book){
        console.log('Book: ' + book);

        async.each(tags, function(tag, done){
            book.tags.create(tag, done);
        }, function(err){
            //Book > Tag
            console.log("Book " + book.Title + " has these tags: ");
            console.log(book.tags())
            //Tag > Book

            Tag.findOne({where: {Name: "Scifi"}, include: 'books'},function(err, foundTag){
                console.log("    - Tag " + foundTag.Name + " has these books:");
                console.log(foundTag.books());

            });
        });
    });
};

Output:

Book Twenty Thousand Leagues Under the Sea has these tags: 
[ { Name: 'Scifi', id: 1 }, { Name: 'Adventure', id: 2 } ]

Tag Scifi has these books:
[ { 
    Title: 'Twenty Thousand Leagues Under the Sea',
    author: 'Jules Verne',
    id: 1 
} ]

#1


0  

If a book can have many tags, and a tag can have many books, it sounds like you need the hasAndBelongsToMany relationship. This relationship is great for many-to-many's that don't have any additional payload.

如果一本书可以有很多标签,而一个标签可以有很多书,那么听起来你需要hasAndBelongsToMany关系。对于没有任何额外负载的多对多,这种关系非常有用。

common/models/book.json

{
  "name": "Book",
  "base": "PersistedModel",
  "idInjection": true,
  "options": {
    "validateUpsert": true
  },
  "properties": {
    "Title": {
      "type": "string",
      "required": true
    },
    "Author": {
      "type": "string"
    }
  },
  "validations": [],
  "relations": {
    "tags": {
      "type": "hasAndBelongsToMany",
      "model": "Tag",
      "foreignKey": ""
    }
  },
  "acls": [],
  "methods": {}
}

common/models/tag.json

{
  "name": "Tag",
  "base": "PersistedModel",
  "idInjection": true,
  "options": {
    "validateUpsert": true
  },
  "properties": {
    "Name": {
      "type": "string",
      "required": true
    }
  },
  "validations": [],
  "relations": {
    "books": {
      "type": "hasAndBelongsToMany",
      "model": "Book",
      "foreignKey": ""
    }
  },
  "acls": [],
  "methods": {}
}

How to access it? Here is an example boot script that creates some tags and books, and accesses them.

如何访问它?下面是一个示例启动脚本,用于创建一些标记和书籍,并访问它们。

server/boot/seed.js

var async = require('async');
module.exports = function(app) {

    var Tag = app.models.Tag;
    var Book = app.models.Book;

    var tags = [{Name: "Scifi"}, {Name: "Adventure"}];

    Book.create({Title: "Twenty Thousand Leagues Under the Sea", author: "Jules Verne"}, function(err, book){
        console.log('Book: ' + book);

        async.each(tags, function(tag, done){
            book.tags.create(tag, done);
        }, function(err){
            //Book > Tag
            console.log("Book " + book.Title + " has these tags: ");
            console.log(book.tags())
            //Tag > Book

            Tag.findOne({where: {Name: "Scifi"}, include: 'books'},function(err, foundTag){
                console.log("    - Tag " + foundTag.Name + " has these books:");
                console.log(foundTag.books());

            });
        });
    });
};

Output:

Book Twenty Thousand Leagues Under the Sea has these tags: 
[ { Name: 'Scifi', id: 1 }, { Name: 'Adventure', id: 2 } ]

Tag Scifi has these books:
[ { 
    Title: 'Twenty Thousand Leagues Under the Sea',
    author: 'Jules Verne',
    id: 1 
} ]