Feathers: كيفية إحضار الجمعيات

تم إنشاؤها على ٨ أغسطس ٢٠١٦  ·  30تعليقات  ·  مصدر: feathersjs/feathers

لذلك قمت بتطوير تطبيق بإطار عمل الريش. لدي خطاف متصل بخدمة قاعدة بيانات أريد الوصول إلى البيانات من خدمة أخرى. هل هذا ممكن وسهل؟ أريد أن تكون هذه الخدمة قادرة على الوصول إلى العديد من ملفات neDB. كيف أقوم بهذا العمل؟

'use strict';

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

    // access other db files here and get data

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

التعليق الأكثر فائدة

نعم. ألق نظرة على مثال كيفية إحضار العناصر ذات الصلة . في الأساس ، يمكنك الوصول إلى خدمة أخرى من خلال hook.app.service('servicename') والاتصال بالطريقة التي تحتاجها. لكي تنتظر الخطاف ، يمكنك إرجاع وعد (يتم حله باستخدام الكائن hook ) وهو ما تقوم به جميع طرق الخدمة بالفعل:

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;
    });
  };
};

ال 30 كومينتر

نعم. ألق نظرة على مثال كيفية إحضار العناصر ذات الصلة . في الأساس ، يمكنك الوصول إلى خدمة أخرى من خلال hook.app.service('servicename') والاتصال بالطريقة التي تحتاجها. لكي تنتظر الخطاف ، يمكنك إرجاع وعد (يتم حله باستخدام الكائن hook ) وهو ما تقوم به جميع طرق الخدمة بالفعل:

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 شكرا جزيلا لك. اعتقدت أنه سيكون بهذه السهولة ، لكن لم أجدها في الوثائق ، لا بد أنني فاتني ذلك.

حسنًا ، هذه مكالمة بحثية لدي قبل الخطاف (فقط إذا كنت بحاجة إلى هذه المعلومات)

أنا فقط أحصل على 25 ولكن هناك المئات. إذا قمت بإزالة الحد ، فسأحصل على 5 عناصر فقط.

ما الذي يحدث وكيف أحصل على كل شيء؟

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;
    });
  };
};

يعتمد ذلك على الخيار الذي تحدده لـ paginate.max في التكوين. إنها وسيلة وقائية بحيث لا يمكن لأي شخص أن يطلب ملايين السجلات عن بُعد. في جميع المحولات الأحدث ، يمكنك إيقاف تشغيل ترقيم الصفحات للحصول على كل السجلات مثل هذا :

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

عندما أفعل ذلك أحصل على 0 سجلات. عندما أزيل ترقيم الصفحات: خطأ أحصل على 25.

هل يظهر npm ls feathers-nedb الإصدار 2.4.1؟ إذا لم يكن الأمر كذلك ، فقد تضطر إلى تحديث package.json وفقًا لذلك.

└── [email protected]

لقد تحققت للتو من أن paginate: false يعمل مع المثال التالي:

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);

أحصل على 700 عنصر تم تسجيلها في وحدة التحكم. هل أضفت عن طريق الخطأ paginate: false في الاستعلام بدلاً من المعلمات الرئيسية؟

وهذا هو ما فعلته:

'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;
    });
  };
};

لا يزال تحصل على 0 نتيجة و 25 مع عدم وجود متغير ترقيم الصفحات و 5 نتائج بلا حدود.

ومع ذلك ، فقد عملت مع هذا:

'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;
    });
  };
};

كما ترى النتائج لم تعد موجودة في page.data ولكنها موجودة فقط في متغير الصفحة.

الدرس المستفاد :)

أوه وشكرا daffl على مساعدتك.

من جانب العميل لا يعمل. (المتغير paginate: false, ).

يتم تمرير query بين العميل والخادم. سأحاول أن أتجنب السماح للعميل بطلب كل ما يلزم (إذا كانت قاعدة البيانات الخاصة بك تحتوي على مليون سجل ، فستقتل كل من الخادم والعميل). إذا لم تكن هناك طريقة للتغلب عليها ، فيجب عليك تعيين معامل استعلام خاص (على سبيل المثال $paginate ) من params.query إلى params في رابط على الخادم:

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;
    }
  }
});

أتفهم التحذير من عدم السماح بتقسيم الصفحات من جانب العميل ، ومع ذلك ، فإن الأداة التي أقوم بصنعها مخصصة لي فقط للتشغيل محليًا. شكرا مرة أخرى على كل شيء.

daffl مرحبًا ، أنا أستخدم الكود الذي نشرته لاسترداد مشاركات المستخدم.

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;
    });
  };
};

لكن هذا يتسبب في دخول الخادم في حلقة لا نهائية وتعطل تطبيق العقدة في النهاية.

أنا أستخدم MySQL كقاعدة بيانات خاصة بي متصلة بالتتابع.

ما الخطأ الذي افعله؟

تحديث

لقد أعددت رابطًا مشابهًا للمشاركات لملء حقل المستخدم بناءً على الحقل postedBy . لذلك على ما يبدو ، سيؤدي ربط المستخدم إلى تشغيل خطاف المنشور والذي بدوره سيؤدي إلى تشغيل ربط المستخدم الأصلي وتستمر الحلقة مما يؤدي إلى حلقة لا نهائية وتجاوز في الذاكرة.

أي أفكار حول كيفية ملء عنصر ذي صلة ضحل فقط ، أي أن الخطاف سيسحب فقط العناصر ذات الصلة على المستوى الأول فقط.

daffl فكرتك رائعة ، على الرغم من أن الكود لم يعمل.
اضطررت إلى تغيير hook.paginate إلى hook.params.paginate لجعله يعمل.
وقمت بتغيير بسيط حتى تتمكن من إرسال ما تريده هناك.
حتى تتمكن من $ paginate: {value: false} لتعطيل ترقيم الصفحات أو
$ paginate: {value: {default: 100، max: 2000}} لإلغاء ترقيم الصفحات

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

هناك شيء آخر يجب مراعاته وهو ، عند تعطيل ترقيم الصفحات ، لا تكون البيانات في res.data ولكن الدقة نفسها.

@ ثروات التكنولوجيا أنت على حق. لقد قمت بتحديث مقتطف الشفرة الخاص بي. يجب أن يعمل هذا:

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;
    }
  }
});

أعتقد أنه إذا تم ضبط $ paginate على false (وهذا هو الهدف من هذا الخطاف ، لتعطيله ...) ، فإن if سيكون خطأً أيضًا. يمكن

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;
    }
  }
});

أهلا. هل يمكن أن يخبرني أحدهم ما إذا كانت خدمات الريش تحتوي على وظيفة findOne أو كيفية تنفيذها؟ شكرا!
سي سي daffl

A findOne هو فقط find مع $limit من 1:

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

سألتهاdaffl لأن النمس لديه findOne وأنا اقترحت أنه لا يبحث في كل مجموعة الباقي إذا تم العثور على شيء بالفعل. لذلك ، فكرت في findOne كشيء أكثر ذكاءً ثم البحث مع Limit = 1 ... لهذا السبب سألت.

عادة ما أفعل هذا من أجل إيجاد سريع واحد:

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

لقد قمت للتو بإنشاء مكون إضافي لطريقة .findOne() : feathers-findone

لم أتمكن من العثور على أي مثال حول كيفية إضافة الحل البديل $ paginate للعميل. لذلك قمت بإنشاء خطاف سابق يتم تشغيله من ملف app.hooks.js مع بعض التعديلات:

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;
    }
  };
};

كيف ستشرع في كتابة اختبار وحدة أو تكامل لهذا؟

لذلك إذا كان لدي ما يلي في خطافتي

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

كيف يمكنني "محاكاة" Context.app.service في اختبار الوحدة الخاصة بي؟

هل أحتاج إلى إضافته إلى السياق الخاص بي قبل الكائن؟

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

أنا أستخدم وحدة الاختبار التلقائي التي تم إنشاؤها من مولد الريش الإضافي.
https://generator.feathers-plus.com/get-started/#unit -test-for-a-hook

أم يجب أن أستخدم اختبار التكامل بدلاً من ذلك؟

لقد سلكت طريق السخرية منذ بعض الوقت. أعتقد أنها فكرة سيئة للغاية. سيكون عليك في النهاية أن تسخر من الريش أكثر وأكثر. لا يوجد حارس يعمل على أداء حرائك كما يفعل الريش ويمكنك الحصول على سلبيات كاذبة ، كما فعلت أنا.

يعد إنشاء تطبيق Feathers سريعًا جدًا ، لذا استخدم Feathers بدلاً من mocks. هذه هي الطريقة التي يتم بها تقييم اختبار CLI +.

لقد كتبت مقال يشير إلى هذا. https://medium.com/feathers-plus/automatic-tests-with-feathers-plus-cli-4844721a29cf

شكرًا إيدي ، لقد رأيت ذلك ، مقالًا رائعًا ، ساعدني حقًا.

كنت أكافح بشأن كيفية إضافة التطبيق إلى كائن السياق الخاص بي ولكني أعمل عليه في النهاية ، على ما أعتقد!

    const app = feathers();

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

ثم اضطررت إلى تعديل الاختبار بحيث استخدم غير متزامن.

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,
    });
  });

هل هذه هي الطريقة الصحيحة للقيام بذلك أم أن هناك طريقة أفضل؟

تبدو جيدا

@ ثروات التكنولوجيا أنت على حق. لقد قمت بتحديث مقتطف الشفرة الخاص بي. يجب أن يعمل هذا:

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;
    }
  }
});

يمكن استخدام حد الاستعلام $: فارغة لتجاوز أيضا

هل كانت هذه الصفحة مفيدة؟
0 / 5 - 0 التقييمات