What is the best way to search through a Meteor collection using React? - mongodb

I've got a collection that I'd like users to be able to search through and display the results accordingly. A while ago I was achieving this with the easy-search package, which uses blaze.
What are the most common approaches to this kind of problem with React? How do people search through their collections and display data accordingly?
I have a component for a book, which has images, author, title, etc. Each entry in the Books collection can be represented with this Book component, so what I'd like to do with this search is allow users to type in a title, or author name, or ISBN, etc, and display the matched results as one of these Book components.
Here's the collection:
Books = new Mongo.Collection('books');
BooksSchema = new SimpleSchema({
isbn: {
type: String,
label: 'ISBN'
},
title: {
type: String,
label: 'Title'
},
author: {
type: String,
label: 'Author'
},
condition: {
type: Number,
label: 'Condition'
},
conditionNotes: {
type: String,
label: 'Condition notes'
},
price: {
type: Number,
label: 'Price'
},
images: {
type: String,
label: 'Images',
autoform: {
afFieldInput: {
type: 'cloudinary'
}
}
},
postedOn: {
type: Date,
label: 'Posted on',
autoValue: function() {
return new Date();
},
autoform: {
type: 'hidden'
}
}
});
The Book component just renders the title, isbn, author, price etc in a presentable way. What I'm looking to do, again, is have a component that contains a search bar that can connect to this Mongo collection and query it, presenting results that match whatever the user typed in.

Related

How to navigate through documents in a circuler linked list fashion in MongoDB?

I have a really simple User model.
const userSchema = mongoose.Schema({
name: {
type: String,
required: true,
},
email: {
type: String,
required: true,
},
password: {
type: String,
required: true,
},
address: {
type: String,
default: null,
},
description: {
type: String,
default: null,
},
active: {
type: Boolean,
default: true,
},
interests: [
{
type: String,
default: null,
},
],
favorites: [
{
type: mongoose.Schema.Types.ObjectId,
ref: 'User',
default: null,
},
],
});
I have a use-case where the client should be able to navigate through the users one by one in a circular fashion. I was able to implement the functionality for getting the next and previous user relative to a specific user through the
this answer.
However, the issue with this is that if I try to get the previous document on the first document in the Users collection, it of course returns an empty object. And same is the case when I try to get the next document on the last document.
I want to tweak it so that if I try to get the previous document on the first document, it would return me the last document, and if I try to get the next document on the last document, it would return me the first document. Just like how you traverse through a circular linked list. Any help would be appreciated! Thanks.

Mongoose deep multi level population

i'm building e-commerce app with NodeJS and MongoDB. I have schema for product categories with subcategories, I need to populate on multi-level on subcategories. For Example i have parent category "Mens Clothing" with subcategory "T-shirts" with sub "Graphic T-shirts" and so on. So i need to populate every subcategory on every subcategory.
Here is my Schema:
{
name: String,
slug: {
type: String,
unique: true,
required: true,
},
featuredPhoto: String,
description: String,
parent: {
type: mongoose.Schema.Types.ObjectId,
default: null,
ref: "Categories",
},
subCategories: [{
type: mongoose.Schema.Types.ObjectId,
ref: "Categories",
}],
and here is my controller:
const categories = await categoryModel
.find({ parent: null })
.select("name _id slug parent subCategories")
.populate([
{
path: "subCategories",
model: "Categories",
select: "name slug _id subCategories",
populate: {
path: "subCategories",
model: "Categories",
select: "name slug _id subCategories",
},
},
]);
As you can see i have two nested populations, but if i have sub-categories in sub-sub categories it's not populated. I want to populate every subcategory no matter how many sub categories it's have.
Here is screenshoot:

Moongose: .populate on key with white space doesn't work

I'm using Express and Mongoose to do some database actions. When trying to populate a path where the key includes a whitespace, it basically get's ignored.
MongoDB Model:
const OrgCrimeSchema = new Schema({
gracePeriod: { type: Date, default: Date.now() },
Technical: {
description: String,
difficulty: Number,
owner: { type: Schema.Types.ObjectId, ref: 'User' },
},
'Social Engineering': { // This one causes issues
description: String,
difficulty: Number,
owner: { type: Schema.Types.ObjectId, ref: 'User' },
},
});
Find + Populate:
const now = Date.now();
const allOrgCrimes = await OrgCrime.find({ gracePeriod: { $lte: now } })
.populate('Technical.owner', 'name')
.populate('Social Engineering.owner', 'name');
console.log(allOrgCrimes['Social Engineering'][0].owner);
//5fca3b4a86e77b5c8e58b683
console.log(allOrgCrimes['Technical'][0].owner);
// { name: 'npc_alice', _id: 5fae6d7ee60018434108369c }
I assume the path is not being populated because of a white space in the key. I've tried both dot notation and typing {path: 'Social Engineering', select: 'name -id'}, without luck.
Is there any way around this without having to rewrite the schema structure?
In short, there is no way, if we wanted to populate multiple paths at the same time there is this way
for exmaple
Story
.find(...)
.populate('book author') // space delimited path names
.exec()
you can see space delimited path names.
When you pass a key with space,mongoose consider it as populate multiple
As poined out by Mohammad Yaser Ahmadi, there is no solution to this issue today because of populate assumes you're populating multiple instead of trying to read a path name with a space in between. How I 'solved' this was to rewrite the model to this:
const OrgCrimeSchema = new Schema({
gracePeriod: { type: Date, default: Date.now() },
roles: [{
role: String,
description: String,
difficulty: Number,
owner: { type: Schema.Types.ObjectId, ref: 'User' },
}]
})
And then the populate actually get's easier:
.populate('roles.owner', 'name')

Data modelling using mongoose for sports bet tracking application

I built a simple sports bet tracker application while I am learning the MERN stack. Users can track their sports bets and see various stats on their performance. It currently only supports tracking single bets (1 selection in bet) and I wish to add to ability to track multiple bets (>1 selections in bet). Each selection in a multiple bet will have the same data as a single bet eventDate, sport, event, selection odds etc. I'm just looking for some advice on the best way to add this in. Bet model currently is as follows
const betSchema = mongoose.Schema({
eventDate: {
type: Date
},
sport: {
type: String
},
event: {
type: String
},
market: {
type: String
},
selection: {
type: String
},
odds: {
type: Number
},
result: {
type: String,
default: 'Pending'
},
stake: {
type: Number
},
owner: {
type: mongoose.Schema.Types.ObjectId,
required: true,
ref: 'User'
}
}, {
timestamps: true
})
Going forward a bet can have one selection or many in it so I was thinking this should become an array. If it has one selection the odds for the bet will be the odds of that selection but if it has multiple selections in it the odds of the bet will be the odds of the selections multiplied. If one selection in a multiple bet loses the bet is a loss. I was thinking something like the following setup but I'm not sure as I don't have much database experience any help who'd be appreciated.
const betSchema = mongoose.Schema({
selections: [{
sport: {
type: String
},
event: {
type: String
},
eventDate: {
type: Date
},
market: {
type: String
},
selection: {
type: String
},
result: {
type: String
},
odds: {
type: Number
},
}],
odds: {
type: Number
},
stake: {
type: Number
},
result: {
type: String,
default: 'Pending'
},
owner: {
type: mongoose.Schema.Types.ObjectId,
required: true,
ref: 'User'
}
}, {
timestamps: true
})
I went with the Schema shown in the question, not sure if it's the best solution but it works for what I am trying to build.

How to make sanity io array select as multiselect?

I have a lot of tags, and I need to select a lot for each document. It is uncomfortable to click one by one every time. Also I see selected elements. How can I remake it into somefield like a multiselect? It could be even native. Or how to select all tags at once?
I am using array:
{
title: 'Language',
name: 'language',
type: 'array',
options: {
layout: 'grid'
},
of: [{
type: 'reference',
title: 'Lang',
to: {
type: 'settingLanguages'
}
}],
},
Dropdown example (Add field to schema):
{
title: 'Genre',
name: 'genre',
type: 'string',
options: {
list: [
{ title: 'Sci-Fi', value: 'sci-fi' },
{ title: 'Western', value: 'western' },
],
},
},
This is currently not possible out of the box with the default array component, but you should be able to create an input like this by building a custom input for it with the behaviour you want.
More on how to build custom inputs: https://www.sanity.io/docs/extending/custom-input-widgets