跳到主要内容

_id 为 String 类型时出现 Mongoose Cast to ObjectId failed 解决方案

· 阅读需 2 分钟
{
"_id" : "Football",
"ancestors" : [
"Categories",
"Sports and fitness"
],
"parent" : "Sports and fitness"
}

模型定义如下

var mongoose = require('mongoose');

var Category = mongoose.Schema({
_id: String
});

var categorySchema = mongoose.Schema({
ancestors: [Category],
parent: [Category]
});


// Initiate database connection
var db = mongoose.createConnection('mongodb://localhost/Categories');
db.on('error', console.error.bind(console, 'connection error:'));
db.once('open', function callback () {
console.log("openDB categories");
});

module.exports.category = db.model('Category', categorySchema);
var categoryModel = require('../models/Category');
var Category = categoryModel.category;

exports.getAncestors = function(req, res) {
if (req.params.id == undefined){res.send("no id specified!"); return;}

Category.findOne({_id: 'Football'}, 'ancestors', function(err, ancestors){
if(err) console.log(err);

res.send(ancestors);
});
}

运行时发生错误

{ message: 'Cast to ObjectId failed for value "Football" at path "_id"',
name: 'CastError',
type: 'ObjectId',
value: 'Football',
path: '_id' }

解决方案

mongoose 默认将 _id 设为 ObjectId 类型。

var categorySchema = mongoose.Schema({
_id: String,
ancestors: [{type: String }],
parent: {type: String}
},{ _id: false });

var Category = mongoose.model( "Category", categorySchema );

JavaScript 和 Node.js 开源库收集

· 阅读需 5 分钟

怎样获得 express 所有的注册路由呢?

· 阅读需 2 分钟

比如我们注册了如下的路由

app.get('/', function (...) { ... });
app.get('/foo/:id', function (...) { ... });
app.post('/foo/:id', function (...) { ... });

然后想要获得的东东是这样的形式:

{
get: [ '/', '/foo/:id' ],
post: [ '/foo/:id' ]
}

该肿么办呢?

在 express 3.x 中

只需要 app.routes 就可以啦

在 express 4.x 中

Applications - built with express()

app._router.stack

Routers - built with express.Router()

router.stack

更多的答案尽在 StackOverflow how-to-get-all-registered-routes-in-express

mongoose 连接超时参数

· 阅读需 3 分钟

最近在项目中经常发生登录卡死的状况,由于是使用的 passport 单点登录,所以只能一步步排查,加日志。

最后发现是卡在一个 mongodb 查询那里,后来去官网查询后,发现查询超时时间默认是无限大的,所以导致我们看到的现象是 http 无返回,导致 http 超时了 , 因此 nginx 报 502 错误。

找到了 mongoose 文件的Connection部分,在下面可以看到有一些连接参数,其中就有 socketTimeoutMS 和 connectTimeoutMS,点击进入 mongodb 官方文档,可以看到Server 的参数中,socketTimeoutMS 默认是无限大的,这在连接外网 mongodb 时可能导致一些问题,我们需要加上超时参数。

var options = {
server: {
socketOptions: {
autoReconnect: true,
connectTimeoutMS: 10000,
socketTimeoutMS: 10000,
},
},
}

// Good way to make sure mongoose never stops trying to reconnect
mongoose.connect(uri, options);

有待观察后补充


尝试后发现,这个 socketTimeoutsocket 变成时的设置 timeout 是一个效果,闲置超时时间,但是在 linux 下似乎没有什么不正常,在 windwos 上就是启动后,过了这个时间就会抛出一个 timeout 错误。

启动 redis 出现 Creating Server TCP listening socket *:6379 bind No such file or directory

· 阅读需 2 分钟

平时直接启动没问题,今天出了这个问题,启动失败,加上配置文件也不行。

D:\redis2.8>redis-server.exe
[8264] 08 Nov 09:28:43.943 # Warning: no config file specified, using the default config. In order to specify a config file use redis-server.exe /path/to/redis.conf
[8264] 08 Nov 09:28:43.948 # Creating Server TCP listening socket *:6379: bind: No such file or directory

Redis 报错:

[6644] 02 Apr 23:11:58.976 # Creating Server TCP listening socket *:6379: bind: No such file or directory

的解决方案如下按顺序输入如下命令就可以连接成功

1. redis-cli.exe
2. shutdown
3. exit
4. redis-server.exe redis.windows.conf

yarn 命令 cheat sheet

· 阅读需 3 分钟

Why Yarn

Yarn is Super Fast!!

Yarn caches every package it downloads so it never needs to again. It also parallelizes operations to maximize resource utilization so install times are faster than ever.

Common NPM commands in Yarn

NPM CommandYarn CommandDescription (wherever necessary)
npm installyarn
yarn install
Will install packages listed in the package.json file
npm install pkg-name
npm install --save pkg-name
yarn add pkg-nameBy default Yarn adds the pgk-name to package.json and yarn.lock files
npm install pkg-name@1.0.0yarn add pgk-name@1.0.0
npm install pkg-name --save-devyarn add pkg-name --dev
npm install pkg-name --peeryarn add pkg-name--peer
npm install pkg-name --optionalyarn add --optional
npm install -g pkg-nameyarn global add pkg-nameCareful, yarn add global pkg-name adds packages global and pkg-name locally!
npm updateyarn upgradeNote: It's called upgrade in yarn
npm uninstall pkg-nameyarn remove pkg-name
npm run script-nameyarn run script-name
npm inityarn init
npm packyarn packCreates a compressed gzip archive of the package dependencies
npm linkyarn link
npm outdatedyarn outdated
npm publishyarn publish
npm runyarn run
npm cache cleanyarn cache clean
npm loginyarn login (and logout)
npm testyarn test
npm install --productionyarn --production
npm --versionyarn version
npm infoyarn info

New Commands in Yarn

Yarn CommandDescription
yarn why pkg-name Builds a dependency graph on why this package is being used
yarn cleanFrees up space by removing unnecessary files and folders from dependencies
yarn licenses ls  Inspect the licenses of your dependencies
yarn licenses generate-disclaimer  Automatically create your license dependency disclaimer

References

https://yarnpkg.com/en/docs/


参考

https://github.com/areai51/yarn-cheatsheet

https://shift.infinite.red/npm-vs-yarn-cheat-sheet-8755b092e5cc

Linux Shell 中的反引号,单引号,双引号

· 阅读需 4 分钟

概念

反引号位 (`) 位于键盘的 Tab 键的上方、1 键的左方。注意与单引号 (') 位于 Enter 键的左方的区别。 在 Linux 中起着命令替换的作用。命令替换是指 shell 能够将一个命令的标准输出插在一个命令行中任何位置。

如下,shell 会执行反引号中的 date 命令,把结果插入到 echo 命令显示的内容中。

[root@localhost sh] $ echo The date is \`date\`
The date is 2011年 03月 14日 星期一 21:15:43 CST

单引号、双引号用于用户把带有空格的字符串赋值给变量事的分界符。

[root@localhost sh] $ str="Today is Monday"
[root@localhost sh] $ echo $str
Today is Monday

如果没有单引号或双引号,shell 会把空格后的字符串解释为命令。

[root@localhost sh] $ str=Today is Monday
bash: is: command not found

单引号和双引号的区别。单引号告诉 shell 忽略所有特殊字符,而双引号忽略大多数,但不包括 $、\、`。

[root@localhost sh] $ testvalue=100
[root@localhost sh] $ echo 'The testvalue is $testvalue'
The testvalue is $testvalue
[root@localhost sh] $ echo "The testvalue is $testvalue"
The testvalue is 100

场景

我在使用 gitlab 时,使用 shell runner 时,将对应的变量放在了一个单引号的命令中,但是其中的变量始终不替换,后来换成双引号就好了,所以查了一下 linux 下单引号双引号的区别。

webpack 再使用变量作为 require 路径时,打包 Critical dependencies 警告

· 阅读需 3 分钟

有的小伙伴可能在开发时需要动态加载模块

常规思路,如果模块有固定的父级路径,比较好办:

var foo = require("./dir/"+somevaribale+".js");

这样即可,进行根据条件不同进行加载。

但是也有情况下,路径是完全不可预测的。

比如我们需要加载一个任意的绝对路径,我们可能会这样写。

var module_path= "/dir/"+somevariable+".js";
var foo= require(module_path);

在 node 后端环境,这样是没有问题的。

但是在 webpack 打包的时候,这样就会有警告了: Critical dependencies

这个问题,是源自 webpack 中的require context问题。

在 github 上也有相关的讨论:

我试了这种方式,发现可以,所以分享一下,但是我没有在 electron 环境下尝试。

// webpack.config.js

{
module: {
// require
unknownContextRegExp: /$^/,
unknownContextCritical: false,

// require(expr)
exprContextRegExp: /$^/,
exprContextCritical: false,

// require("prefix" + expr + "surfix")
wrappedContextRegExp: /$^/,
wrappedContextCritical: false
}
}

git 提交了一些敏感信息,如何进行彻底删除

· 阅读需 2 分钟

如果自己一个不小心的提交了一些敏感的信息到 git 上面,

而自己的项目有可能被其他人看到,如果查看历史记录还是能看到自己提交那些文件。那么如果彻底从历史记录中的删除这些文件 操作是在 Linux 下面做的 :

git filter-branch --index-filter 'git rm --cached --ignore-unmatch db.properties*' --prune-empty --tag-name-filter cat -- --all
git push origin master --force
rm -rf .git/refs/original/
git reflog expire --expire=now --all
git gc --prune=now
git gc --aggressive --prune=now

禁止 iframe 记录浏览器历史

· 阅读需 4 分钟

NTS 框架中采用了新的方式记录浏览器的操作历史,因此在某些带 IFRAME 载入内容的项目中不希望这个 IFRAME 的变化影响到整个系统的操作历史,下面给出两种禁止 IFRAME 记录操作历史的解决方案,各有利弊视具体情况选取。

方案一

原理:利用 location 的 replace 方法载入新页面,关于 replace 方法的描述: When a document is replaced, it is also removed from the history object. Moreover, the user interface navigation methods, such as the Back and Forward buttons, will no longer access the URL. 分析:此方案有个前提条件就是父窗体需要有对 iframe 窗体的访问权限,因此此方案一般用于 iframe 载入的内容和父窗体是同域或者同父域的情形。 范例: case 1

第一种方案主要是通过 replace 来将 url 替换而不是 push 到浏览器历史中

document.getElementById('abc').contentWindow.location.replace(url);

方案二

原理:先销毁已有 iframe 再创建一个新的,然后通过新的 iframe 载入新的页面内容 分析:不存在跨域问题,但是会有 iframe 不断创建销毁的额外开销 范例: untitled2.png

第二种方式主要是删除 iframe 节点之后重新创建一个 iframe 元素。

iframe = document.createElement('iframe');
document.body.appendChild(iframe);
iframe.src = url;

11