I need to ask - I've got a /users endpoint and I want to add tasks to user, just like that: /users/:username/tasks. Should I create another model and route? I don't know how to add an ID to an array in Mongoose model and add a slug with mongoose-url-slugs.
I want it to be RESTful as much as I can. So this: /users/:username/tasks or /tasks/:username? If first, I need to know how to add ID to tasks in that model:
import mongoose from 'mongoose'
const User = mongoose.Schema({
username: String,
email: String,
password: String,
tasks: Array
}, {
timestamps: true
})
export default mongoose.model('User', User)
In my opinion, I believe you should create a new model tasks.
You can use a reference to tasks model like that:
tasks: [{ type: Schema.Types.ObjectId, ref: 'tasks' }]
https://mongoosejs.com/docs/populate.html
This route's better because you're adding a task to the user and not a user to the task
/users/:username/tasks
And to link then you can use mongoose's virtual: https://mongoosejs.com/docs/tutorials/virtuals.html
Ex: https://github.com/Automattic/mongoose/issues/6608
UserSchema.virtual('tasks', {
lookup: (doc) => {
return {
from: 'tasks',
let: { userId: '$_id' },
pipeline: [{
$match: {
$expr: {
$and: [{
$eq: ['$refId', '$$userId']
}]
}
}
}, {
$project: { name: 1, createdAt: 1 }
}
],
as: 'tasks',
}
}
});
userModel.find().populate('tasks').lean(true);
Related
I have a Java service that writes logs in JSON format, they are then picked up by filebeat and sent to Elastic. I would like to be able to set one of the ECS fields (event.duration) described here
I set up a net.logstash.logback.encoder.LoggingEventCompositeJsonEncoder encoder, and I set the event.duration field in MDC before calling logging method. The output looks like this:
{
"#timestamp": "2021-12-07T10:41:59.589+01:00",
"message": "message",
"event.duration": "5606000000",
"service": {
"name": "logging.application.name_IS_UNDEFINED",
"type": "java"
},
"log": {
"logger": "com.demo.Demo",
"level": "WARN"
},
"process": {
"thread": {
"name": "main"
}
},
"error": {}
}
However, in Kibana I see event.duration as a JSON inside the flat field:
flat
{
"event.duration": "10051000000"
}
How can I make it on the same level as other ECS fields like event.name?
You should create an ingest pipeline using the dot_expander processor in order to transform your dotted field into an object:
PUT _inest/pipeline/de-dot
{
"processors" : [
{
"dot_expander": {
"field": "event.duration"
}
}
]
}
Then you need to make sure that your indexing process references this pipeline, i.e. ...?pipeline=de-dot
I've got the JSON data behind the scenes, that's it
[{"aid":100000,"name":"JYCM201609010250","rtsp":"947|100000|3750","statuz":"1","updateTime":"2017-05-31"},{"aid":100001,"name":"gui","rtsp":"947|100000|3750","statuz":"0","updateTime":"2017-05-31"}]
Background and foreground code are as follows
#Autowired
private MediaImpl media;
#ResponseBody
#RequestMapping(value = "/media",method = RequestMethod.GET)
public List<Media> MediaAll(){
System.out.println("------------------------------------------------------");
return media.findAll();
}
JS code is as follows
<script>
$(document).ready(function () {
$('#table_id_example').DataTable({
"iDisplayLength": 10,
"bLengthChange": false,
"ajax": {
"url": "/media",
"dataType": "json",
"success": function (json) {
console.log(json)
}
},
"columns": [
{
"data": 'aid'
},
{
"data": 'name'
},
{
"data": 'rtsp'
},
{
"data": 'statuz'
},
{
"data": 'updateTime'
}
]
});
});
html code is as follows
The console code
VM178:10 (2) [{…}, {…}]0: {aid: 100000, name: "JYCM201609010250", rtsp: "947|100000|3750", statuz: "1", updateTime: "2017-05-31"}1: {aid: 100001, name: "gui", rtsp: "947|100000|3750", statuz: "0", updateTime: "2017-05-31"}length: 2__proto__: Array(0)
There is no error in the front-end console, and no errors in the back end.But the data is not available
There are a couple of problems here. The first is that datatables expects data in a data element of the json response, such as:
{
data: [{"aid":100000,"name":"JYCM201609010250","rtsp":"947|100000|3750","statuz":"1","updateTime":"2017-05-31"},{"aid":100001,"name":"gui","rtsp":"947|100000|3750","statuz":"0","updateTime":"2017-05-31"}]
}
You should be able to use ajaxSrc: "" on your DataTable settings.
The second problem is with your ajax settings. DataTables states you can not supply the success callback in the ajax settings as it uses this internally.
Documentation on both of these issues:
https://datatables.net/reference/option/ajax
Assuming you are using DataTables 1.10.x
My app send multiply request to server each time I insert new item to store. When the first item inserted it calls POST once, one more item ... twice and so on.
Im new at ExtJs, so can you help me in solving some qustions:
First of all what the sync method do, why (GET, POST, PUT, DELETE) methods are not called without store.sync() method invok?
Why my post method multiply requests?
Why store.remove() (DELETE) method throws 400 error (Bad request) when the PUT method works fine?
Thank you in advance
my edit controller:
Ext.define('MVC.controller.Edit', {
extend: 'Ext.app.Controller',
init: function () {
this.control({
'editForm > button#SaveRecord': {
click: this.onSaveButtonClick
},
'editForm > button#DeleteButton': {
click: this.onDeleteButtonClick
}
});
},
onSaveButtonClick: function (btn) {
//get reference to the form
var detailView = btn.up('editForm');
//get the form inputs
var data = detailView.getValues();
//see if the record exists
var store = Ext.getStore('TestStore');
console.log(data.id);
var record = store.getById(data.id);
if (!record) {
record = Ext.create('MVC.model.Note', {
title: data.title,
created: new Date(),
updated: new Date(),
text: data.text
});
store.insert(0, record);
store.sync();
Ext.MessageBox.alert('Created', record.id);
return;
}
record.set(data);
store.sync();
//manually update the record
detailView.updateRecord();
},
onDeleteButtonClick: function (btn) {
//get reference to the form
var detailView = btn.up('editForm');
//get the form inputs
var data = detailView.getValues();
var store = Ext.getStore('TestStore');
var record = store.getById(data.id);
store.remove(record);
store.sync();
}
});
Store :
Ext.define('MVC.store.TestStore', {
extend : 'Ext.data.Store',
requires : [
'MVC.model.Note'
],
storeId : 'TestStore',
model : 'MVC.model.Note',
autoLoad: false,
proxy: {
type : 'rest',
url: 'rest/notes',
actionMethods : {
create : 'POST',
read : 'GET',
update : 'PUT',
destroy : 'DELETE'
},
reader: {
type: 'json',
rootProperty: 'data'
},
writer: {
type: 'json'
}
}
});
And model:
Ext.define('MVC.model.Note', {
extend: 'Ext.data.Model',
fields: [
{
name: 'id',
type: 'string'
},
{
name: 'title',
type: 'string'
},
{
name: 'created',
type: 'date'
},
{
name: 'updated',
type: 'date'
},
{
name: 'text',
type: 'string'
}
]
});
Try to use record's methods:
1)Add proxy to you'r model like this:
Ext.define('MVC.model.Note',{
extend: 'Ext.data.Model',
fields: [
{
name: 'id',
type: 'string'
},
{
name: 'title',
type: 'string'
},
{
name: 'created',
type: 'date'
},
{
name: 'updated',
type: 'date'
},
{
name: 'text',
type: 'string'
}],
proxy:
{
type: 'rest',
url: 'rest/notes',
reader:
{
type: 'json'
}
}
});
2)Now you can use methods: record.save() - will send PUT if it was loaded to store from server and record have id, or POST if this record was created with record.create();
record.destroy() - will send DELETE to server with id of record;
You can use Ext.ModelManager.getModel('Model_name').load(id) to send GET request to server for single record.
3)Use store.load() to GET array of records from server
I'm begginner in Ext JS and i want to send my Java Form to an ext js store who has a defined model :
This is my Java Form :
public class Form {
private member1;
private member2;
private List<AnotherType> membersList;
//getters and setters
}
This is my store :
Ext.define('MyApp.store.Mystore', {
extend : 'Ext.data.Store',
model : 'MyApp.model.MyModel',
proxy : {
type: 'rest',
url : '/myapp/url/for/findForm',
reader: {
type: 'json'
rootProperty : 'form'
},
writer: {
type: 'json'
}
}
}
How to define MyModel for include list of members ?
And how to use this list once my store is loaded ?
(it's a list to load a combox)
Thanks !
Your models could look something like this. I've used a naming pattern similar to what you used in your question.
Ext.define("MyApp.model.Form", {
extend: "Ext.data.Model",
fields: [
{name: "member1", type: "string"},
{name: "member2", type: "string"},
],
hasMany: {
model: "MyApp.model.AnotherType",
name: "membersList",
associationKey: "membersList"
}
});
Ext.define("MyApp.model.AnotherType", {
extend: "Ext.data.Model",
fields: [
{name: "value", type: "string"},
{name: "label", type: "string"},
]
});
You can create a combo box like this.
Ext.create("Ext.form.ComboBox", {
fieldLabel: "Members",
store: Ext.getStore("MyApp.store.Mystore").getAt(0).membersList(),
queryMode: "local",
displayField: "label",
valueField: "value",
renderTo: Ext.getBody()
});
Note that the above is just an example using the first MyApp.model.Form in your store. You'll likely want to create the combo box in a more generic way, but I'm not sure of the specifics for your case.
I am new for sencha touch. I need to create, delete, update a member record throughout jersey java. Here is my code
view.js
Ext.define('bluebutton.view.BlueButton.testing', {
extend: 'Ext.form.Panel',
xtype: 'testing',
requires: [
'bluebutton.view.BlueButton.TransactionList',
'bluebutton.view.BlueButton.MemberPopUp',
'bluebutton.view.BlueButton.MemberDetail',
'bluebutton.store.BlueButton.MemberList',
],
config: {
id:'register',
items :[
{
xtype: 'textfield',
name: 'name',
label: 'Name'
},
{
xtype: 'emailfield',
name: 'email',
label: 'Email'
},
{
xtype: 'button',
text: 'Send',
handler: function(button) {
var form = Ext.getCmp('register');
values = form.getValues();
var myStore= new Ext.data.Store({
model: 'bluebutton.model.BlueButton.MemberList'
});
var newModel = Ext.ModelMgr.create({ 'memberId': 1,
'name': 2,
'imgUrl': 3
}, 'bluebutton.model.BlueButton.MemberList');
myStore.add(newModel);
myStore.sync();
}
}
],
}
});
Model.js
Ext.define('bluebutton.model.BlueButton.MemberList', {
extend: 'Ext.data.Model',
config: {
idProperty: 'memberModel',
fields: [
{ name: 'memberId' },
{ name: 'name' },
{ name: 'imgUrl' },
{ name: 'age' },
{ name: 'address' },
{ name: 'pointAvalaible' },
{ name: 'lastVisited' },
],
proxy: {
type: 'ajax',
actionMethods: {
create : 'POST',
read : 'POST', // by default GET
update : 'POST',
destroy: 'POST'
},
url: 'http://localhost:8080/RESTFulExample/rest/json/metallica/testingj'
},
}
});
Store.js
Ext.define('bluebutton.store.BlueButton.MemberList', {
extend: 'Ext.data.Store',
requires: [
'bluebutton.model.BlueButton.MemberList'
],
config: {
grouper: {
groupFn: function (record) {
return record.get('name')[0];
}
},
model :'bluebutton.model.BlueButton.MemberList',
storeId :'memberStore',
autoLoad:false,
pageSize: 5,
clearOnPageLoad: false,
data: [
]
}
});
Jersey.java
#POST
#Path("/testingj")
// #Consumes("application/x-www-form-urlencoded")
#Consumes(MediaType.APPLICATION_JSON)
public Response too(MultivaluedMap<String, String> form) {
return Response.status(201).entity(form).build();
}
But I keep getting this error
XMLHttpRequest cannot load localhost:8080/RESTFulExample/rest/json/metallica/testingj?_dc=1358408853016.
Origin localhost is not allowed by Access-Control-Allow-Origin.
Please guide me solution.
You are getting this response because of browser's security constraint for cross origin requests, which means from javascript you can call only those urls which are in same domain. Since your service is running on 8080 post so browser consider it from other domain.
There are various ways to do cross domain request, out of which you should read about:
JsonP
Enabling CORS on server
But since mobile's security constraints are different from desktop's browser constraints so the same thing might work in mobile even though it doesn't work in browser. For more details check this out : Loading store data with rest proxy from server in Sencha Touch 2
In your case I would recommend you to add JsonP support to your services and use JsonP proxy instead of AJAX & REST proxy.