我很抱歉,但经过一天的研究和尝试所有不同的组合和npm包之后,我仍然不确定如何处理以下任务。
设置:
我有一个这样的架构:
var trackingSchema = mongoose.Schema({
tracking_number: String,
zip_code: String,
courier: String,
user_id: Number,
created: { type: Date, default: Date.now },
international_shipment: { type: Boolean, default: false },
delivery_info: {
recipient: String,
street: String,
city: String
}
});
现在用户给了我一个搜索字符串,一个字符串数组,它将是我想要搜索的子字符串:
var search = ['15323', 'julian', 'administ'];
现在我想查找那些文档,其中tracking_number
,zip_code
或delivery_info
中的任何字段都包含我的搜索元素。
我该怎么做?我知道有索引,但我可能需要复合索引,或者文本索引?然后,对于搜索,我可以使用RegEx
或$text $search
语法?
问题在于我有几个要查找的字符串(我的search
),以及要查看的几个字段。由于其中一个方面,每个方法在某些时候都失败了。
答案 0 :(得分:2)
您的使用案例非常适合text search。
在可搜索字段上的架构上定义文本索引:
trackingSchema.index({
tracking_number: 'text',
zip_code: 'text',
'delivery_info.recipient': 'text',
'delivery_info.street': 'text',
'delivery_info.city': 'text'
}, {name: 'search'});
将搜索字词加入单个字符串,然后使用$text
查询运算符执行搜索:
var search = ['15232', 'julian'];
Test.find({$text: {$search: search.join(' ')}}, function(err, docs) {...});
即使这会将您的所有搜索值作为单个字符串传递,但仍会对值进行逻辑或搜索。
答案 1 :(得分:1)
好的,我想出了这个。
我的架构现在有一个额外的字段search
,其中包含我所有可搜索字段的数组:
var trackingSchema = mongoose.Schema({
...
search: [String]
});
使用预保存挂钩,我填充此字段:
trackingSchema.pre('save', function(next) {
this.search = [ this.tracking_number ];
var searchIfAvailable = [
this.zip_code,
this.delivery_info.recipient,
this.delivery_info.street,
this.delivery_info.city
];
for (var i = 0; i < searchIfAvailable.length; i++) {
if (!validator.isNull(searchIfAvailable[i])) {
this.search.push(searchIfAvailable[i].toLowerCase());
}
}
next();
});
为了提高性能,我还将该字段编入索引(同样也是user_id
,因为我限制了搜索结果):
trackingSchema.index({ search: 1 });
trackingSchema.index({ user_id: 1 });
现在,在搜索时,我首先列出我想在数组中寻找的所有子串:
var andArray = [];
var searchTerms = searchRequest.split(" ");
searchTerms.forEach(function(searchTerm) {
andArray.push({
search: { $regex: searchTerm, $options: 'i'
}
});
});
我在find()
中使用此数组并将其与$and
链接:
Tracking.
find({ $and: andArray }).
where('user_id').equals(userId).
limit(pageSize).
skip(pageSize * page).
exec(function(err, docs) {
// hooray!
});
这很有效。
答案 2 :(得分:1)
为什么不尝试
var trackingSchema = mongoose.Schema({
tracking_number: String,
zip_code: String,
courier: String,
user_id: Number,
created: { type: Date, default: Date.now },
international_shipment: { type: Boolean, default: false },
delivery_info: {
recipient: String,
street: String,
city: String
}
});
var Tracking = mongoose.model('Tracking', trackingSchema );
var search = [ "word1", "word2", ...]
var results = []
for(var i=0; i<search.length; i++){
Tracking.find({$or : [
{ tracking_number : search[i]},
{zip_code: search[i]},
{courier: search[i]},
{delivery_info.recipient: search[i]},
{delivery_info.street: search[i]},
{delivery_info.city: search[i]}]
}).map(function(tracking){
//it will push every unique result to variable results
if(results.indexOf(tracking)<0) results.push(tracking);
});