Feathers: Cara mengambil asosiasi

Dibuat pada 8 Agu 2016  ·  30Komentar  ·  Sumber: feathersjs/feathers

Jadi saya telah mengembangkan aplikasi dengan kerangka bulu. Saya memiliki pengait yang terpasang ke layanan basis data yang ingin saya akses data dari layanan lain. Apakah ini mungkin, dan mudah? Saya ingin layanan itu dapat mengakses beberapa file neDB. Bagaimana cara melakukannya?

'use strict';

module.exports = function(options) {
  return function(hook) {

    // access other db files here and get data

    hook.data = {
        putDataHere: newData
    };
  };
};

Komentar yang paling membantu

Ya. Lihat contoh cara mengambil item terkait . Pada dasarnya, di hook Anda, Anda dapat mengakses layanan lain melalui hook.app.service('servicename') dan memanggil metode yang Anda butuhkan. Agar pengait menunggu, Anda dapat mengembalikan Janji (yang diselesaikan dengan objek hook ) yang dengan mudah dilakukan oleh semua metode layanan:

module.exports = function(options) {
  return function(hook) {
    return hook.app.service('otherservice').find({
      query: { name: 'David' }
    }).then(page => {
      const davids = page.data;

      hook.data.davids = davids;
      // Or you can replace all the data with
      hook.data = { davids };

      // IMPORTANT: always return the `hook` object in the end
      return hook;
    });
  };
};

Semua 30 komentar

Ya. Lihat contoh cara mengambil item terkait . Pada dasarnya, di hook Anda, Anda dapat mengakses layanan lain melalui hook.app.service('servicename') dan memanggil metode yang Anda butuhkan. Agar pengait menunggu, Anda dapat mengembalikan Janji (yang diselesaikan dengan objek hook ) yang dengan mudah dilakukan oleh semua metode layanan:

module.exports = function(options) {
  return function(hook) {
    return hook.app.service('otherservice').find({
      query: { name: 'David' }
    }).then(page => {
      const davids = page.data;

      hook.data.davids = davids;
      // Or you can replace all the data with
      hook.data = { davids };

      // IMPORTANT: always return the `hook` object in the end
      return hook;
    });
  };
};

@daffl Terima kasih banyak. Saya pikir akan semudah ini, tetapi tidak dapat menemukannya di dokumentasi, saya pasti melewatkannya.

Ok jadi ini adalah panggilan pencarian yang saya miliki sebelum kait (hanya jika Anda memerlukan info itu)

Saya hanya mendapatkan 25 tetapi ada ratusan. Jika saya menghapus batas, saya hanya mendapatkan 5 item.

Apa yang terjadi dan bagaimana saya mendapatkan semuanya?

module.exports = function(options) {
  return function(hook) {

    const dataSet = hook.params.query.dataSet;
    const userVector = hook.params.query.userVector;

    return hook.app.service('data').find({
      query: { dataSet: dataSet, $limit:2000 }
    }).then(page => {

      // lots of magic here

      //console.log(page.data);

      hook.result = page.data;

      return hook;
    });
  };
};

Itu tergantung pada opsi apa yang Anda tetapkan untuk paginate.max dalam konfigurasi. Ini adalah perlindungan sehingga seseorang tidak bisa hanya meminta jutaan catatan dari jarak jauh. Di semua adaptor yang lebih baru, Anda dapat mematikan pagination untuk mendapatkan semua catatan seperti ini :

return hook.app.service('data').find({
      paginate: false,
      query: { dataSet: dataSet }
    }).then(data => {
      // data is an array
    });

Ketika saya melakukan itu saya mendapatkan 0 catatan. Ketika saya menghapus pagination: false saya mendapatkan 25.

Apakah npm ls feathers-nedb menunjukkan v2.4.1? Jika tidak, Anda mungkin harus memperbarui package.json .

└── [email protected]

Saya baru saja memverifikasi bahwa paginate: false berfungsi dengan contoh berikut:

const feathers = require('feathers');
const rest = require('feathers-rest');
const socketio = require('feathers-socketio');
const hooks = require('feathers-hooks');
const nedb = require('feathers-nedb');
const bodyParser = require('body-parser');
const handler = require('feathers-errors/handler');
const NeDB = require('nedb');

// A Feathers app is the same as an Express app
const app = feathers();
const db = new NeDB({
  filename: './data/messages.db',
  autoload: true
});

// Parse HTTP JSON bodies
app.use(bodyParser.json());
// Parse URL-encoded params
app.use(bodyParser.urlencoded({ extended: true }));
// Register hooks module
app.configure(hooks());
// Add REST API support
app.configure(rest());
// Configure Socket.io real-time APIs
app.configure(socketio());
// Register our memory "users" service
app.use('/todos', nedb({
  Model: db,
  paginate: {
    default: 20,
    max: 50
  }
}));
// Register a nicer error handler than the default Express one
app.use(handler());

const promises = [];

for(let i = 0; i < 700; i++) {
  promises.push(app.service('todos').create({ text: `Item #${i}`}));
}

Promise.all(promises).then(function() {
  app.service('todos').find({
    paginate: false,
    query: {}
  }).then(data => console.log(data));
});

// Start the server
app.listen(3333);

Saya mendapatkan 700 item yang masuk ke konsol. Apakah Anda secara tidak sengaja menambahkan paginate: false ke dalam kueri alih-alih parameter utama?

Inilah yang saya lakukan:

'use strict';

module.exports = function(options) {
  return function(hook) {

    const dataSet = hook.params.query.dataSet;
    const userVector = hook.params.query.userVector;

    return hook.app.service('data').find({
      paginate: false,
      query: { dataSet: dataSet, $limit:2000 }
    }).then(page => {

      // lots of magic here
      console.log(page.data);

      hook.result = page.data;

      return hook;
    });
  };
};

Masih mendapatkan 0 hasil dan 25 dengan variabel pagination tidak ada dan 5 hasil tanpa batas.

Namun, saya membuatnya bekerja dengan ini:

'use strict';

module.exports = function(options) {
  return function(hook) {

    const dataSet = hook.params.query.dataSet;
    const userVector = hook.params.query.userVector;

    return hook.app.service('data').find({
      paginate: false,
      query: { dataSet: dataSet }
    }).then(page => {

      // lots of magic here
      console.log(page);

      hook.result = page;

      return hook;
    });
  };
};

Seperti yang Anda lihat, hasilnya tidak lagi di halaman.data tetapi hanya di variabel halaman.

Pelajaran yang didapat :)

Oh dan terima kasih @daffl atas bantuan Anda.

Di sisi klien itu tidak berfungsi. (variabel paginate: false, ).

Hanya query yang dikirimkan antara klien dan server. Saya akan mencoba dan menghindari membiarkan klien meminta semua keutuhan (jika database Anda memiliki sejuta catatan, itu akan membunuh keduanya, server dan klien). Jika tidak ada jalan lain, Anda harus memetakan parameter kueri khusus (mis. $paginate ) dari params.query ke params di hook di server:

app.service('data').before({
  find(hook) {
    if(hook.params.query && hook.params.query.$paginate) {
      hook.params.paginate = hook.params.query.$paginate === 'false' || hook.params.query.$paginate === false;
      delete hook.params.query.$paginate;
    }
  }
});

Saya memahami peringatan untuk tidak mengizinkan pagination di sisi klien, namun, alat yang saya buat hanya untuk saya jalankan secara lokal. Terima kasih sekali lagi untuk semuanya.

@daffl Hai, saya menggunakan kode yang Anda poskan untuk mengambil kiriman yang dimiliki pengguna.

module.exports = function(options) {
  return function(hook) {
    // hook.getPosts = true;
    const id = hook.result.id;
    console.log("id");

    return hook.app.service('posts').find({
      paginate: false,
      query: { postedBy: id }
    }).then(function(posts){
      console.log("posts");
      // Set the posts on the user property
      hook.result.posts = posts.data;
      // Always return the hook object or `undefined`
      return hook;
    });
  };
};

Tetapi ini menyebabkan server masuk ke loop tak terbatas dan aplikasi simpul akhirnya macet.

Saya menggunakan MySQL sebagai DB saya yang terhubung dengan sekuel.

Apa yang saya lakukan salah?

Memperbarui

Saya telah menyiapkan pengait serupa untuk posting untuk mengisi bidang pengguna berdasarkan bidang postedBy . Jadi tampaknya, kait pengguna akan memicu kait posting yang pada gilirannya akan memicu kait pengguna asli dan loop terus menghasilkan loop tak terbatas dan memori meluap.

Setiap ide bagaimana mengisi hanya item terkait yang dangkal, yaitu, kail hanya akan menarik item terkait hanya pada tingkat pertama.

@daffl Ide Anda luar biasa, meskipun kodenya tidak berfungsi.
Saya harus mengubah hook.paginate menjadi hook.params.paginate untuk membuatnya berfungsi.
Dan saya membuat sedikit perubahan sehingga Anda dapat mengirim apa pun yang Anda inginkan ke sana.
jadi Anda dapat $paginate : {value: false} untuk menonaktifkan pagination atau
$paginate: { nilai: {default: 100, max: 2000}} untuk mengganti pagination

app.service('data').before({ find(hook) { if(hook.params.query.$paginate) { hook.params.paginate = hook.params.query.$paginate.value; delete hook.params.query.$paginate; } } });

Satu hal lagi yang perlu dipertimbangkan adalah, ketika pagination dinonaktifkan, data tidak ada di res.data tetapi res itu sendiri.

@fortunes-technology Anda benar. Saya memperbarui cuplikan kode saya. Ini harus bekerja:

app.service('data').before({
  find(hook) {
    if(hook.params.query && hook.params.query.$paginate) {
      hook.params.paginate = hook.params.query.$paginate === 'false' || hook.params.query.$paginate === false;
      delete hook.params.query.$paginate;
    }
  }
});

Saya pikir jika $paginate disetel ke false (yang merupakan inti dari hook ini, untuk menonaktifkannya... ), if juga akan menjadi false. Mungkin

app.service('data').before({
  find(hook) {
    if(hook.params.query && hook.params.query.hasOwnProperty('$paginate')) {
      hook.params.paginate = hook.params.query.$paginate === 'false' || hook.params.query.$paginate === false;
      delete hook.params.query.$paginate;
    }
  }
});

Hai, yang di sana. Bisakah seseorang memberi tahu saya jika layanan bulu memiliki fungsi findOne atau bagaimana cara mengimplementasikannya? Terima kasih!
cc @daffl

findOne hanyalah find dengan $limit dari 1:

app.service('myservice').find({ query: { name: 'test', $limit: 1 } })
 .then(page => page.data[0])
 .then(result => console.log('Got', result);

@daffl saya bertanya karena luwak memiliki findOne dan saya menyarankan agar tidak mencari semua koleksi lainnya jika sesuatu sudah ditemukan. Jadi, saya berpikir tentang findOne sebagai sesuatu yang lebih cerdas daripada pencarian dengan limit=1... Itu sebabnya saya bertanya.

Saya biasanya melakukan ini untuk findOne cepat:

const employee = (await context.app.service('employees').find({ query: { userId: user.id }, paginate: false }))[0];

Saya baru saja membuat plugin untuk metode .findOne() : feathers-findone

Saya tidak dapat menemukan contoh tentang cara menambahkan solusi $paginate untuk klien. Jadi saya membuat kait sebelum yang dijalankan dari file app.hooks.js dengan beberapa modifikasi:

module.exports = function () {
  return context => {
    if (context.params.query && hook.params.query.hasOwnProperty('$paginate')) {
      context.params.paginate = context.params.query.$paginate === 'false' || context.params.query.$paginate === false;
      delete context.params.query.$paginate;
    }
  };
};

Bagaimana Anda menulis unit atau tes integrasi untuk ini?

jadi jika saya memiliki yang berikut di hook saya

const records = getItems(context);
records.authors = await context.app.service('users') .find({ query: { _id: { $in: records.authorIds } } }, context.params);

bagaimana cara saya "mengejek" context.app.service dalam pengujian unit saya?

apakah saya perlu menambahkannya ke objek contextBefore saya?

contextBefore = { type: 'before', params: { provider: 'socketio', user: { _id: 1 } }, data: { _id: 1, }, };

saya menggunakan unit-test auto yang dihasilkan dari generator feathers-plus.
https://generator.feathers-plus.com/get-started/#unit -test-for-a-hook

atau haruskah saya menggunakan tes integrasi saja?

Saya telah menempuh rute mengejek beberapa waktu lalu. Saya pikir itu ide yang sangat buruk. Anda akhirnya harus mengejek Feathers lebih dan lebih. Tidak ada jaminan bahwa tiruan Anda berfungsi seperti bulu dan Anda bisa mendapatkan negatif palsu, seperti yang saya lakukan.

Membuat aplikasi Feathers sangat cepat, jadi gunakan Feathers alih-alih mengolok-olok. Begitulah cara pendekatan tes cli+.

Saya menulis artikel yang mengacu pada ini. https://medium.com/feathers-plus/automatic-tests-with-feathers-plus-cli-4844721a29cf

terima kasih eddyy, saya sudah melihatnya, artikel yang bagus, sangat membantu.

saya berjuang tentang cara menambahkan aplikasi ke objek konteks saya tetapi akhirnya berhasil, saya pikir!

    const app = feathers();

    contextBefore = {
      type: 'before',
      params: { provider: 'socketio', user: { _id: 1 } },
      data: {
        _id: 1,
      },
      app,
    };

Kemudian saya harus mengubah tes sehingga menggunakan async.

it('patch test', async () => {
    contextBefore.app.use('users', {
      async find() {
        return { data: [ { expectedResultObj1 }, { expectedResultObj2 } ] };
      }
    });
    contextBefore.data = {
      _id: 1,
    };
    assert(true);

    await hookToTest()(contextBefore);

    assert.deepEqual(contextBefore.data, {
      _id: 1,
      expectedResultObject1,
      expectedResultObject2,
    });
  });

Apakah itu cara yang benar untuk melakukannya atau adakah cara yang lebih baik?

Kelihatan bagus

@fortunes-technology Anda benar. Saya memperbarui cuplikan kode saya. Ini harus bekerja:

app.service('data').before({
  find(hook) {
    if(hook.params.query && hook.params.query.$paginate) {
      hook.params.paginate = hook.params.query.$paginate === 'false' || hook.params.query.$paginate === false;
      delete hook.params.query.$paginate;
    }
  }
});

dapat menggunakan kueri $limit : null untuk mem-bypass juga

Apakah halaman ini membantu?
0 / 5 - 0 peringkat