How to define fields in an AbstractIndexCreationTask? - ravendb

I've got an AbstractIndexCreationTask in my application as follows:
public class EventsForMainQueries : AbstractIndexCreationTask<Event>
{
public EventsForMainQueries()
{
Map = docs => from doc in docs
select new
{
DatePublished = doc.DatePublished,
IsDeleted = doc.IsDeleted,
Author = doc.Author,
EventDate = doc.EventDate
};
Index(x => x.DatePublished, FieldIndexing.Default);
Sort(x => x.DatePublished, SortOptions.String);
Index(x => x.EventDate, FieldIndexing.Default);
Sort(x => x.EventDate, SortOptions.String);
}
}
however, RavenDB is still creating the following auto index.
What do I need to change in my IndexCreationTask to prevent the temp/auto index being generated?

Did you ever call IndexCreation.CreateIndexes(typeof(EventsForMainQueries).Assembly, documentStore); or in any other way create that index on the server?
You can also "force" which index you're reading from by using:
session.Query<Event, EventsForMainQueries>()....
If your index is not on the server, this query should error not create a temp index.

Try this
Storing the index:
EventsForMainQueries.Execute(DocumentStore);
Quering the events:
Session.Query<Event, EventsForMainQueries>()

Related

How to sort result set using computed fields (type-graphql)

I'm using type-graphql and typeorm. Is there a way to sort the result based on a computed field. Specifically, I want to return a list of Clients and sort the list based on a computed field: "sortName". Sort name is simply a string of the clent's "firstName lastName" or "lastName FirstName". The decision on how to generate the sortName is based on a flag in the Company table (that way the user can control how they want to view their clients). I just don't know how to do the sort prior to sending back to the front-end app. I know I can create a view and do it in sql - but I'd like to know if it's possible to do in code.
import {Arg, Ctx, Field, FieldResolver, ID, InputType, ObjectType, Query, Resolver, Root,} from 'type-graphql'
import {Client} from '../entities/Client'
import {ClientNameSort, Company} from '../entities/Company'
import {MyContext} from '../types/MyContext'
#InputType()
export class ClientsOptions {
#Field(() => ID)
companyId!: string
}
#ObjectType()
#Resolver(Client)
export class ClientResolver {
#FieldResolver(() => String)
async sortName(#Root() client: Client, #Ctx() { companyLoader }: MyContext) {
const company:Company = await companyLoader.load(client.companyId)
if (!company) {
throw new Error(`Missing rec for Company Id ${client.companyId}`)
}
if (company.clientNameSort === ClientNameSort.FIRST_NAME) {
return `${client.firstName} ${client.lastName} ${client.id}`
} else {
return `${client.lastName} ${client.firstName} ${client.id}`
}
}
#Query(() => [Client])
async clients(#Arg('options') options: ClientsOptions) {
const clientList = await Client.find({ where: { companyId: options.companyId } })
return clientList;
}
}
I believe you have to do the sorting on the "clients" method. Therefore i am not sure the field resolver is going to help you. You better separate that into a utility function and reuse it in both methods.
To to the sorting on the clients method:
if you use mongodb, maybe you can do an aggregated query that will create this virtual field and order by it
if you use another DB , you will have to look if they have this kind of feature
If you don't want to do sorting through DB, you can get the array of clients and do a sort
clients.sort((a,b) => sortByCompanyName(company.CLIENT_NAME_SORT, a, b))
getFullIdentificator(order, client) {
if (order === ClientNameSort.FIRST_NAME) {
return `${client.firstName} ${client.lastName} ${client.id}`
} else {
return `${client.lastName} ${client.firstName} ${client.id}`
}
}
sortByCompanyName(order, prev, next) {
return getFullIdentificator(order, prev) > getFullIdentificator(order, next) ? 1 : -1
}

How can i create multiple editors whit class name

I try to create multiple ckeditors classic.
The problem is that i dont know how many i will have. So i init them by className.
This init the editors and work, but dont send anything trough ajax. So when i try to update the textarea only i can send the last editor because window.editor is overwrite.
I try then to store in an array but i cant pass th for neditor value because its a then so it executes when the for loop is done, so neditor is always 2.
How can i made it work? Idont understand very well promises
Thanks!
import ClassicEditor from './ckeditor5-build-classic';
var allEditors = document.querySelectorAll('.usarCkeditor');//i have 2 editors in that case
for (var neditores = 0; neditores < allEditors.length; neditores++) {
ClassicEditor.create(allEditors[neditores])
.then(editor => {
window.editor = editor;//window.editor is alway the last editor
})
.catch(err => {
console.error(err.stack);
});
}
This is other version :
for (var neditores = 0; neditores < allEditors.length; neditores++) {
window["editor" + neditores] = 'paco';
ClassicEditor.create(document.querySelector('#' + allEditors[neditores].attributes.id.value))
.then(editor => {
console.log(editor);
window["editor" + neditores] = editor;
console.log(neditores);//always 2 so it overwrites the array
})
.catch(err => {
console.error(err.stack);
});
}
//window.editor -> [0] = 'paco';[1] = 'paco';[2]= ckeditor
Please notice that querySelectorAll returns an HTMLNodeList not an Array.
If you want to initialize editor over multiple elements with classes you can do it for example in this way. All references to editors instances will be stored in window.editors object.
window.editors = {};
document.querySelectorAll( '.editor' ).forEach( ( node, index ) => {
ClassicEditor
.create( node, {} )
.then( newEditor => {
window.editors[ index ] = newEditor
} );
} );
This is a working sample: https://codepen.io/msamsel/pen/pXONjB?editors=1010

How to retrieve id of just inserted firestore document (with angularfire2)?

I'm inserting a new document into my firestore collection like so:
this.afs.collection<Client>('clients').add(this.form.value).then(docRef => {
console.log("Need to output the firestore generated doc id of the document here: ...")
})
Try
this.afs.collection<Client>('clients').add(this.form.value).then(docRef => {
console.log(docRef.id);
})
Got it: then() takes a union type (http://www.typescriptlang.org/docs/handbook/advanced-types.html): void | DocumentReference.
Therefore needs to be addressed like this:
this.afs.collection<Client>('clients').add(this.form.value).then(docRef => {
console.log((docRef) ? (<DocumentReference>docRef).id : 'void') // docRef of type void | DocumentReference
})
You can generate a key by yourself.
...
this.generatedKey = this.generateNewKey('clients');
...
this.afs.collection<Client>(`clients`).doc(this.generatedKey)
.set({ someField: 'some value' })
.then(docRef => {
console.log("Self generated doc ID: ...", this.generatedKey )
})
generateNewKey(ref: any) {
const _ref = firebase.firestore().collection(ref).doc();
const newKey = _ref.id;
return newKey;
}

Yii2 Sort multiple parameters URL

I have an endpoint in yii2 where I need to sort by multiple parameters. Im using ActiveDataProvider. This is the enpdoint:
public function actionIndex($client)
{
$sort = new Sort([
'attributes'=> ['name','mail','crdate']
]);
$query = Customer::find()
->andWhere(['client' => $client])
->orderBy($sort->orders);
$provider = new ActiveDataProvider(['query' => $query]);
return $provider->getModels();
}
Now sorting by a single parameter as in: customers?client=1&sort=mail works fine.
I want to sort by multiple parameters though. How should I do this in the url?
Set
$sort = new Sort([
'attributes'=> ['name','mail','crdate'],
'enableMultiSort' => true,
]);
Now you can pass multiple sort column by separating them with , like
?sort=name,mail
If you prepend name with - you get descending order otherwise it's ascending.
If you want to change , separator to something else set it in separator configuration key for Sort object.
You should try search model for Costumer model
public function search($params)
{
$query = Costumer::find();
$dataProvider = new ActiveDataProvider([
'query' => $query,
]);
$this->load($params);
if (!$this->validate()) {
return $dataProvider;
}
$query->andFilterWhere([some condition for search]);
return $dataProvider;
}

Does boosting documents work with wildcard searches?

Given the following index definition, will the boost be applied when a query such as Content:(Morel*) is used?
I've added two documents to the database, one of type Article and one of type Response. Both with identical Title, Body and Tags. When I run the above query against the index in Raven Studio, both documents come back with the same $Temp:Score.
AddMap<Article>(docs => from doc in docs
select new
{
Content = new object[]
{
doc.Title,
doc.Body,
doc.Tags
}
}.Boost(5)); // <-- Boost Article documents.
AddMap<Response>(docs => from doc in docs
select new
{
Content = new object[]
{
doc.Title,
doc.Body,
doc.Tags
}
});
Index("Content", FieldIndexing.Analyzed);
I'm searching using the following code
var searchTerms = string.Join(" OR ",
q.Split(new[] { ' ' },
StringSplitOptions.RemoveEmptyEntries)
.Select(x => string.Format("{0}*",x)));
var query = RavenSession.Advanced
.LuceneQuery<IIndexedEntity, AllDocumentByContent>()
.Include(x => x.Author)
.Search("Content", searchTerms);
Yes, it will be applied when you make the query.