How to search by properties of an index - algolia

I have to retrieve a list of users that consumes an app with a particular ID:
const users = algoliaClient.initIndex('users')
return users.search('myId123', { hitsPerPage: 50 });
But the users objects are just like this:
{apps: [
{id: 'myId123'},
{id: 'anotherId456'},
{id: 'anotherId789'},
]}
How can I search the index for items with an apps property that contains an object with such Id?

If you add a period between the attribute and the sub-objects attribute name, you can add this to the 'Searchable Attributes' configuration value to allow it to be searchable. For example, if I wanted the id attribute from the array of the apps attribute to be searchable, I would configure it like so:

Related

Is it possible to populate nested references in Mongoose?

I'm new to MongoDB, trying to populate data from another collection into a response. The simplest example would be as follows:
const CartSchema = new Schema({
items: [{
product: { type: Schema.Types.ObjectId, ref: 'product' },
qty: Number
}],
...
});
I'm able to use .populate() when the relationships are at the root level, but in the above example, I have an array of items with their own properties, e.g. qty, plus an _id reference to a product. I would like to populate the product object into each car item, but can't seem to find any examples on what's the "right" way to do it.
Cart.findById(id)
.populate('products') // <-- something like this
.then(record => ... )
.catch(next);
I know that I could probably do a separate .find() on the products collection after locating the cart record and manually extend the initial object, but I was hoping there was a way to populate the data within the original query?
You can try this, it will work for you.
Cart.findById(id)
.populate('items.product')
.then(record => ... )
.catch(next);
.populate('items.product') will populate the product object of all the cart item present in the array.

Send more than one term to algolia search

I'm implementing algolia search in my site and i want to get a set of data matching any id's i send to the search, so i need to know how could i send more than one parameter to the search, so i can send a set of ids, something like this:
let client = algoliasearch(APP_ID, API_KEY),
index = client.initIndex(INDEX_NAME);
let term=["3223212","2423434"];
index.search(term, callback)
This is not working right now, have any idea? or even how could i achieve my goal using another algolia feautre like filtering for instance?
If you're trying to retrieve objects by their objectIDs (which you can manually set at creation time to match your database ids), you can simply use the getObjects method.
Extract from the documentation:
You can also retrieve a set of objects:
index.getObjects(['myObj1', 'myObj2'], function(err, content) {
console.log(content);
});
If you're trying to list all the records that belong to a group with a specific id, you can use a facet that will contain this id and filter on it.
Inside your record:
{
"group_id": "3223212",
// or
"group_ids": ["3223212", "2423434"]
}
Inside your index settings:
{
attributesForFaceting: [
'onlyFilter(group_id)'
]
}
At query time:
let ids = ["3223212", "2423434"];
let filters = ids.map(id => `group_id:${id}`).join(' OR ');
index.search('', { filters: filters }, callback);

return specific properties of array element - MongoDB/ Meteor

I have documents in games collection.Each document is responsible for holding the data that requires to run the game. Here's my document structure
{
_id: 'xxx',
players: [
user:{} // Meteor.users object
hand:[] //array
scores:[]
calls:[]
],
table:[],
status: 'some string'
}
Basically this is a structure of my card game(call-bridge). Now what I want for the publication is that the player will have his hand data in his browser( minimongo ) along with other players user, scores, calls fields. So the subscription that goes down to the browser will be like this.
{
_id: 'xxx',
players: [
{
user:{} // Meteor.users object
hand:[] //array
scores:[]
calls:[]
},
{
user:{} // Meteor.users object
scores:[]
calls:[]
},
// 2 more player's data, similar to 2nd player's data
],
table:[],
status: 'some string'
}
players.user object has an _id property which differentiates the user. and in the meteor publish method, we have access to this.userId which returns the userId who is requesting the data.It means I want the nested hand array of that user whose _id matches with this.userId. I hope this explanations help you write more accurate solution.
What you need to do is "normalize" your collection. Instead of having hand,scores, calls in the players field in the Games collection, what you can do is create a separate collection to hold that data and use the user _id as the "Key" then only reference the user _id in the players field. For example.
Create a GameStats collection(or whichever name you want)
{
_id: '2wiowew',
userId: 1,
hand:[],
scores:[],
calls:[],
}
Then in the Games collection
{
_id: 'xxx',
players: [userId],
table:[],
status: 'some string'
}
So if you want to get the content of the current user requesting the data
GameStats.find({userId: this.userId}).hand
EDIT
They do encourage denormalization in certain situations, but in the code you posted above, array is not going to work. Here is an example from the mongoDB docs.
{
_id: ObjectId("5099803df3f4948bd2f98391"),
name: { first: "Alan", last: "Turing" },
birth: new Date('Jun 23, 1912'),
death: new Date('Jun 07, 1954'),
contribs: [ "Turing machine", "Turing test", "Turingery" ],
views : NumberLong(1250000)
}
To get a specific property from an array element you may write something as in the below line db.games.aggregate([{$unwind:"$players"},{$project:{"players.scores":1}}]); this gives us only the id and scores fields

Multiple entry select2 and angular model fetched by $resource

I am having some difficulty figuring out how to make it all work together. Here is what I would like to do:
The model is fetched using $resource from the rest API:
var itemResource = $resource('http://blabla.com/items/:id');
$scope.item = itemResource.get({id: '12345'});
The returned item has some fields among which is one array field that lists the ids of the categories:
{
"item_name: "some value",
"categories": ["cat_id1", "cat_id7", "cat_id8"]
}
In the UI I want these categories to be shown as editable multi select. The user should not operate using ids, but rather he should see and be able to chose string representations which come from the mapping within the application. So in html:
<input type"text" ui-select2="categoryOptions" ng-model="item.categories" />
and also in controller:
var categoryMapping = [
{id: "cat_id1", text: "CategoryAlpha"},
...
{id: "cat_id8", text: "CategoryOmega"},
...
];
$scope.categoryOptions = {
'multiple': true,
'placeholder': 'Chose categories',
'width': 'element',
'data': categoryMapping,
};
Obviously the pieces of code above are not working and I don't know how to make them work to do what I want. ui-select2 wants the model (item.categories) to be an array of objects {id, text} and I want it to store only the ids in the items in the database and have the mapping separate. I can't be the first one to do it, there must be a solution, please help.
Thanks

Node.js - Mongoose/MongoDB - Model Schema

I am creating a blog system in Node.js with mongodb as the db.
I have contents like this: (blog articles):
// COMMENTS SCHEMA:
// ---------------------------------------
var Comments = new Schema({
author: {
type: String
},
content: {
type: String
},
date_entered: {
type: Date,
default: Date.now
}
});
exports.Comments = mongoose.model('Comments',Comments);
var Tags = new Schema({
name: {
type: String
}
});
exports.Tags = mongoose.model('Tags',Tags);
// CONTENT SCHEMA:
// ---------------------------------------
exports.Contents = mongoose.model('Contents', new Schema({
title: {
type: String
},
author: {
type: String
},
permalink: {
type: String,
unique: true,
sparse: true
},
catagory: {
type: String,
default: ''
},
content: {
type: String
},
date_entered: {
type: Date,
default: Date.now
},
status: {
type: Number
},
comments: [Comments],
tags: [Tags]
}));
I am a little new to this type of database, im used to MySQL on a LAMP stack.
Basically my question is as follows:
whats the best way to associate the Contents author to a User in the
DB?
Also, whats the best way to do the tags and categories?
In MYSQL we would have a tags table and a categories table and relate by keys, I am not sure the best and most optimal way of doing it in Mongo.
THANK YOU FOR YOUR TIME!!
Couple of ideas for Mongo:
The best way to associate a user is e-mail address - as an attribute of the content/comment document - e-mail is usually a reliable unique key. MongoDB doesn't have foreign keys or associated constraints. But that is fine.
If you have a registration policy, add user name, e-mail address and other details to the users collection. Then de-normalize the content document with the user name and e-mail. If, for any reason, the user changes the name, you will have to update all the associated contents/comments. But so long as the e-mail address is there in the documents, this should be easy.
Tags and categories are best modelled as two lists in the content document, IMHO.
You can also create two indices on these attributes, if required. Depends on the access patterns and the UI features you want to provide
You can also add a document which keeps a tag list and a categories list in the contents collection and use $addToSet to add new tags and categories to this document. Then, you can show a combo box with the current tags as a starting point.
As a final point, think through the ways you plan to access the data and then design documents, collections & indices accordingly
[Update 12/9/11] Was at MongoSv and Eliot (CTO 10gen) presented a pattern relevant to this question: Instead of one comment document per user (which could grow large) have a comment document per day for a use with _id = -YYYYMMDD or even one per month depending on the frequency of comments. This optimizes index creation/document growth vs document proliferation (in case of the design where there is one comment per user).
The best way to associate the Content Authors to a User in the MongoDB, is to take an array in Author Collection which keeps an reference to User. Basically Array because One Content/Book may have multiple Authors i.e. you need to associate one Content to many Users.
The best way for category is to create a different collection in your DB and similarly as above keep a array in Contents.
I hope it helps at-least a little.